ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2024-08-03 06:15:10
Exec Total Coverage
Lines: 98 7650 1.3%
Functions: 1 196 0.5%
Branches: 14 6405 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "zq/zquestdat.h"
15 #include "zq/zq_tiles.h"
16 #include "zq/zquest.h"
17 #include "tiles.h"
18 #include "zq/zq_misc.h"
19 #include "zq/zq_class.h"
20 #include "base/zsys.h"
21 #include "base/colors.h"
22 #include "qst.h"
23 #include "gui/jwin.h"
24 #include <base/new_menu.h>
25 #include "base/jwinfsel.h"
26 #include "zc/zc_custom.h"
27 #include "zq/questReport.h"
28 #include "dialog/info.h"
29 #include "dialog/scaletile.h"
30 #include "dialog/rotatetile.h"
31 #include "dialog/alert.h"
32 #include "drawing.h"
33 #include "colorname.h"
34 #include "zq/render.h"
35 #include "zinfo.h"
36 #include <fmt/format.h>
37 #include <functional>
38 #include "zq/moveinfo.h"
39 using std::set;
40
41 extern zcmodule moduledata;
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 9 size_and_pos ok_button(302,562,71,21);
1230 9 size_and_pos cancel_button(376,562,71,21);
1231 9 size_and_pos edit_button(550,562,86,21);
1232 9 size_and_pos hlcbox(742,392,16,16);
1233 9 size_and_pos hov_prev(742,338,50,50);
1234 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 9 size_and_pos fg_prev(648,316,50,50);
1237 9 size_and_pos bg_prev(648+30,316+30,50,50);
1238 9 size_and_pos zoomtile(124,32,16,16,32,32);
1239 9 size_and_pos prev_til_1(648,31,96,96);
1240 9 size_and_pos prev_til_2(752,31,96,96);
1241 9 size_and_pos prev_til_3(648,135,96,96);
1242 9 size_and_pos prev_til_4(752,135,96,96);
1243 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1244 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1245 9 size_and_pos color_info(4,189,1,1,116,8);
1246 9 size_and_pos color_info_btn(24,189,96,21);
1247 9 size_and_pos tool_btns(22,29,2,4,39,39);
1248 9 size_and_pos x_btn(890,5,15,13);
1249 9 size_and_pos info_btn(872,5,15,13);
1250 9 size_and_pos hidegrid_cbox(124,552,16,16);
1251 9 size_and_pos quartgrid_cbox(124,572,16,16);
1252 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1253 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1254 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1255
1256 int32_t c1=1;
1257 int32_t c2=0;
1258 int32_t floating_tile = -1;
1259 int32_t tool = t_pen;
1260 int32_t old_tool = -1;
1261 int32_t tool_cur = -1;
1262 int32_t select_mode = 0;
1263 int32_t drawing=0;
1264
1265 bool qgrid_tool(int tool)
1266 {
1267 switch(tool)
1268 {
1269 case t_pen:
1270 case t_fill:
1271 case t_recolor:
1272 case t_wand:
1273 return true;
1274 }
1275 return false;
1276 }
1277
1278 void set_tool_sprite(int tool, int type)
1279 {
1280 int spr = ZQM_NORMAL;
1281 switch(tool)
1282 {
1283 case t_pen: spr = ZQM_SWORD; break;
1284 case t_fill: spr = ZQM_POTION; break;
1285 case t_recolor: spr = ZQM_WAND; break;
1286 case t_eyedropper: spr = ZQM_LENS; break;
1287 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1288 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1289 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1290 }
1291 MouseSprite::set(spr);
1292 }
1293 void update_tool_cursor()
1294 {
1295 int32_t temp_mouse_x=gui_mouse_x();
1296 int32_t temp_mouse_y=gui_mouse_y();
1297
1298 int32_t type=0;
1299
1300 if(has_selection())
1301 {
1302 switch(tool)
1303 {
1304 case t_select:
1305 case t_wand:
1306 type+=select_mode;
1307 break;
1308 }
1309 }
1310
1311 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1312 {
1313 if(tool_cur==-1)
1314 set_tool_sprite(tool,type);
1315
1316 tool_cur=tool;
1317 }
1318 else if(tool_cur != -1)
1319 {
1320 MouseSprite::set(ZQM_NORMAL);
1321 tool_cur = -1;
1322 }
1323 }
1324
1325 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1326 {
1327 PALETTE tpal;
1328 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1329 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1330 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1331
1332 if(!create_tbar)
1333 {
1334 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1335 }
1336 else
1337 {
1338 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1339 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1340 }
1341
1342 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1343
1344 clear_to_color(preview_bmp, 0);
1345
1346 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1347 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1348 puttile16(preview_bmp,tile,0,0,cs,flip);
1349 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1350
1351 clear_to_color(preview_bmp, 0);
1352 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1353 overtile16(preview_bmp,tile,0,0,cs,flip);
1354 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1355 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1356
1357 unpack_tile(newtilebuf, tile, 0, true);
1358 if(floating_sel)
1359 for(auto q = 0; q < 256; ++q)
1360 if(floatsel[q])
1361 unpackbuf[q] = floatsel[q];
1362 byte tmptile[256];
1363 byte *tmpptr = tmptile;
1364 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1365 pack_tile(newtilebuf,unpackbuf,tile);
1366 clear_to_color(preview_bmp, 0);
1367
1368 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1369 puttile16(preview_bmp,tile,0,0,cs,flip);
1370 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1371
1372 clear_to_color(preview_bmp, 0);
1373 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1374 overtile16(preview_bmp,tile,0,0,cs,flip);
1375 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1376
1377 //Color info
1378 {
1379 auto fh = color_info.yscale = text_height(font);
1380 int y = color_info.y;
1381 int rx = color_info.x+color_info.xscale;
1382 color_info.h = 1;
1383 if(showcolortip)
1384 {
1385 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1386 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1387 auto str = get_tile_colornames(tile,cs);
1388 size_t pos = 0;
1389 char buf[512] = {0};
1390 char cbuf[16] = {0};
1391 while(pos < str.size())
1392 {
1393 y += fh;
1394 if(y+fh > zq_screen_h)
1395 break; //Out of space!
1396 auto endpos = str.find_first_of('\n',pos);
1397
1398 if(endpos == std::string::npos)
1399 {
1400 strcpy(buf,str.substr(pos).c_str());
1401 pos = str.size();
1402 }
1403 else
1404 {
1405 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1406 pos = endpos+1;
1407 }
1408 //Ensure the name fits horizontally
1409 if(text_length(font,buf) > color_info.xscale)
1410 {
1411 size_t pos = 0;
1412 for(; buf[pos]; ++pos)
1413 {
1414 if(buf[pos] == ':')
1415 {
1416 strcpy(cbuf, buf+pos);
1417 buf[pos] = 0;
1418 break;
1419 }
1420 }
1421 size_t clen = text_length(font,cbuf);
1422 size_t dotlen = text_length(font,"..");
1423
1424 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1425 buf[--pos] = 0;
1426 while(buf[pos] == ' ')
1427 buf[pos] = 0;
1428 strcat(buf,"..");
1429 strcat(buf,cbuf);
1430 }
1431 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1432 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1433 ++color_info.h;
1434 }
1435 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1436 }
1437 else
1438 {
1439 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1440 "Show Colors",vc(1),vc(14),0,true);
1441 }
1442 }
1443
1444 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1445
1446 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1447 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1448
1449 if(floating_sel)
1450 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1451 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1452 if(newtilebuf[tile].format==tf8Bit)
1453 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1454 else
1455 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1456
1457 PALETTE temppal;
1458
1459 //palette and mouse
1460 switch(newtilebuf[tile].format)
1461 {
1462 case tf4Bit:
1463 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1464 get_palette(temppal);
1465
1466 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1467 {
1468 size_and_pos const& s = cpalette_4.subsquare(i);
1469 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1470 }
1471
1472 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1473 break;
1474
1475 case tf8Bit:
1476 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1477
1478 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1479 {
1480 size_and_pos const& s = cpalette_8.subsquare(i);
1481 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1482 }
1483
1484 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1485 break;
1486 }
1487
1488 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1489 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1490 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1491
1492 if(c2==0)
1493 {
1494 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1495 }
1496
1497 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1498 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1499 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1500
1501 if(c1==0)
1502 {
1503 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1504 }
1505
1506 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1507 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1508 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1509 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1510 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1511
1512 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1513 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1514
1515 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1516 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1517
1518 bool qgrd = show_quartgrid && qgrid_tool(tool);
1519 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1520 for(int q = 0; q < REFL_MAX; ++q)
1521 {
1522 auto& sqr = reflbtn_grid.subsquare(q);
1523 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1524 }
1525 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1526 for(int q = 0; q < XMODE_MAX; ++q)
1527 {
1528 auto& sqr = xmodebtn_grid.subsquare(q);
1529 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1530 }
1531 for(int q = 0; q < BGMODE_MAX; ++q)
1532 {
1533 auto& sqr = bgmodebtn_grid.subsquare(q);
1534 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1535 }
1536
1537 //tool buttons
1538 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1539 {
1540 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1541 int col = toolbtn%tool_btns.w;
1542 int row = toolbtn/tool_btns.w;
1543
1544 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1545 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1546 }
1547
1548 //coordinates
1549 {
1550 auto mx = gui_mouse_x();
1551 auto my = gui_mouse_y();
1552 int32_t ind = zoomtile.rectind(mx,my);
1553 int32_t temp_x=ind%zoomtile.w;
1554 int32_t temp_y=ind/zoomtile.w;
1555 int color = -1;
1556
1557 bool is8b = newtilebuf[tile].format > tf4Bit;
1558 if(ind > -1)
1559 {
1560 char xbuf[16];
1561 sprintf(xbuf, "x: %d", temp_x);
1562 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1563 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1564 unpack_tile(newtilebuf, tile, 0, false);
1565 byte *si = unpackbuf;
1566 si+=ind;
1567 color = *si;
1568 }
1569 else if(fg_prev.rect(mx,my))
1570 color = c1;
1571 else if(bg_prev.rect(mx,my))
1572 color = c2;
1573 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1574 if(color > -1)
1575 {
1576 get_palette(tpal);
1577 char separator = ' ';
1578 char buf[512] = {0};
1579
1580 int realcol = color+(is8b?0:CSET(cs));
1581 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1582 auto& c = tpal[realcol];
1583
1584 if(tthighlight)
1585 {
1586 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1587 size_and_pos const& csqr = mainsqr.subsquare(color);
1588
1589 int hlcol = getHighlightColor(tpal[realcol]);
1590 int hlthick = 4;
1591 int extraborder = is8b ? 8 : 0;
1592 int borderthick = hlthick+extraborder;
1593
1594 if(is8b)
1595 {
1596 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1597 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1598 }
1599 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1600 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1601 if(xcolor)
1602 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1603 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1604 }
1605
1606 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1607 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1608
1609 strcpy(buf, get_color_name(realcol, is8b).c_str());
1610 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1611
1612 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1613 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1614
1615 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1616 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1617 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1618 if(xcolor)
1619 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1620 }
1621 }
1622
1623 custom_vsync();
1624 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1625 update_tool_cursor();
1626 SCRFIX();
1627 }
1628
1629 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1630 {
1631 unfloat_selection();
1632 if(tile>tile2)
1633 {
1634 zc_swap(tile, tile2);
1635 }
1636
1637 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1638 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1639
1640 int32_t start=tile;
1641 int32_t end=tile2;
1642
1643 // Might have top-right and bottom-left corners selected...
1644 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1645 {
1646 start=tile-(TILECOL(tile)-TILECOL(tile2));
1647 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1648 }
1649
1650 for(int32_t temptile=start; temptile<=end; temptile++)
1651 {
1652 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1653 {
1654 unpack_tile(newtilebuf, temptile, 0, true);
1655
1656 if(flip&1)
1657 {
1658 for(int32_t y=0; y<16; y++)
1659 {
1660 for(int32_t x=0; x<8; x++)
1661 {
1662 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1663 }
1664 }
1665 }
1666
1667 if(flip&2)
1668 {
1669 for(int32_t y=0; y<8; y++)
1670 {
1671 for(int32_t x=0; x<16; x++)
1672 {
1673 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1674 }
1675 }
1676 }
1677
1678 pack_tile(newtilebuf,unpackbuf,temptile);
1679 }
1680 }
1681 }
1682
1683 void rotate_tile(int32_t tile, bool backward)
1684 {
1685 unfloat_selection();
1686 unpack_tile(newtilebuf, tile, 0, true);
1687 byte tempunpackbuf[256];
1688 byte tempx, tempy;
1689
1690 for(tempx=0; tempx<16; tempx++)
1691 {
1692 for(tempy=0; tempy<16; tempy++)
1693 {
1694 if(!backward)
1695 {
1696 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1697 }
1698 else
1699 {
1700 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1701 }
1702 }
1703 }
1704
1705 pack_tile(newtilebuf,tempunpackbuf,tile);
1706 }
1707
1708 static int32_t undocount=128;
1709 byte undotile[256];
1710
1711 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1712 {
1713 byte buf[256];
1714
1715 for(int32_t i=0; i<undocount; i++)
1716 {
1717 newtilebuf[tile].data[i]=undotile[i];
1718 }
1719
1720 if(!(horizontal||vertical))
1721 {
1722 return;
1723 }
1724
1725 unpack_tile(newtilebuf, tile, 0, true);
1726
1727 for(int32_t i=0; i<256; i++)
1728 {
1729 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1730 buf[shift_ind] = unpackbuf[i];
1731 }
1732
1733 if(clear)
1734 {
1735 for(int32_t r=0; r<abs(vertical); r++)
1736 {
1737 for(int32_t c=0; c<16; c++)
1738 {
1739 buf[(vertical>0?r:15-r)*16+c]=0;
1740 }
1741 }
1742
1743 for(int32_t r=0; r<16; r++)
1744 {
1745 for(int32_t c=0; c<abs(horizontal); c++)
1746 {
1747 buf[r*16+(horizontal>0?c:15-c)]=0;
1748 }
1749 }
1750 }
1751
1752 pack_tile(newtilebuf,buf,tile);
1753 }
1754
1755 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1756 {
1757 byte buf[256];
1758
1759 if(!(horizontal||vertical))
1760 {
1761 return;
1762 }
1763
1764 memset(buf,0,256);
1765
1766 for(int32_t i=0; i<256; i++)
1767 {
1768 if(is_in_selection(i%16,i/16))
1769 {
1770 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1771 buf[shift_ind] = floatsel[i];
1772 }
1773 }
1774
1775 memcpy(floatsel,buf,256);
1776 }
1777
1778 void float_selection(int32_t tile, bool clear)
1779 {
1780 if(floating_sel) return;
1781 floating_sel = true;
1782 floating_tile = tile;
1783
1784 unpack_tile(newtilebuf, tile, 0, true);
1785
1786 for(auto q = 0; q < 256; ++q)
1787 {
1788 if(is_in_selection(q%16,q/16))
1789 {
1790 floatsel[q] = unpackbuf[q];
1791 unpackbuf[q] = clear ? 0 : c2;
1792 }
1793 else floatsel[q] = 0;
1794 }
1795
1796 pack_tile(newtilebuf,unpackbuf,tile);
1797 }
1798
1799 void unfloat_selection()
1800 {
1801 if(!floating_sel) return;
1802 floating_sel = false;
1803
1804 unpack_tile(newtilebuf, floating_tile, 0, true);
1805
1806 for(auto q = 0; q < 256; ++q)
1807 {
1808 if(floatsel[q])
1809 {
1810 unpackbuf[q] = floatsel[q];
1811 }
1812 }
1813
1814 pack_tile(newtilebuf,unpackbuf,floating_tile);
1815 floating_tile = -1;
1816 }
1817
1818 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1819 {
1820 if(floating_sel)
1821 {
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(ignore_transparent && floatsel[q]==0)
1825 continue;
1826 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1827 }
1828 return;
1829 }
1830
1831 byte buf[256];
1832 unpack_tile(newtilebuf, tile, 0, true);
1833
1834 for(int32_t i=0; i<256; i++)
1835 {
1836 buf[i]=unpackbuf[i];
1837
1838 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1839 continue;
1840
1841 if(ignore_transparent)
1842 {
1843 if(buf[i]==0)
1844 continue;
1845
1846 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1847 }
1848 else // Don't ignore transparent
1849 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1850 }
1851
1852 pack_tile(newtilebuf,buf,tile);
1853 }
1854
1855 void clear_selection_grid()
1856 {
1857 unfloat_selection();
1858 for(int32_t x=0; x<18; ++x)
1859 {
1860 for(int32_t y=0; y<18; ++y)
1861 {
1862 selection_grid[x][y]=0;
1863 }
1864 }
1865 }
1866
1867 void invert_selection_grid()
1868 {
1869 unfloat_selection();
1870 for(int32_t x=1; x<17; ++x)
1871 {
1872 for(int32_t y=1; y<17; ++y)
1873 {
1874 selection_grid[x][y]=selection_grid[x][y]?0:1;
1875 }
1876 }
1877 }
1878
1879 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1880 {
1881 byte local_grid[16][16];
1882 memset(local_grid, 0, sizeof(local_grid));
1883 for(auto x = 0; x < 16; ++x)
1884 {
1885 for(auto y = 0; y < 16; ++y)
1886 {
1887 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1888 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1889 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1890 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1891 }
1892 }
1893 for(auto x = 0; x < 16; ++x)
1894 {
1895 for(auto y = 0; y < 16; ++y)
1896 {
1897 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1898 }
1899 }
1900 }
1901
1902 void show_edit_tile_help()
1903 {
1904 InfoDialog("Help: Tile Editor", "Hotkeys:"
1905 "\nF1: This Help Dialog"
1906 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1907 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1908 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1909 "\nH/V: Flip | (Shift+)R: Rotate"
1910 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1911 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1912 "\nF12: Screenshot (whole screen)"
1913 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1914 "\nWhen not on Select tools, hold to swap:"
1915 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1916 }
1917
1918 static int move_origin_x=-1, move_origin_y=-1;
1919 static int prev_x=-1, prev_y=-1;
1920 bool __pixel_draw(int x, int y, int tile, int flip)
1921 {
1922 bool ret = false;
1923 switch(tool)
1924 {
1925 case t_pen:
1926 if(flip&1) x=15-x;
1927
1928 if(flip&2) y=15-y;
1929
1930 if(is_in_selection(x,y))
1931 {
1932 if(floating_sel)
1933 {
1934 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1935 }
1936 else
1937 {
1938 unpack_tile(newtilebuf, tile, 0, false);
1939 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1940 pack_tile(newtilebuf, unpackbuf,tile);
1941 }
1942 }
1943 break;
1944
1945 case t_fill:
1946 if(is_in_selection(x,y))
1947 {
1948 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1949 ret = true;
1950 }
1951 break;
1952
1953 case t_recolor:
1954 if(is_in_selection(x,y))
1955 {
1956 if(floating_sel)
1957 {
1958 tf_u = floatsel[(y<<4)+x];
1959 for(int32_t i=0; i<256; i++)
1960 {
1961 if(is_in_selection(i&15,i>>4))
1962 {
1963 if(floatsel[i]==tf_u)
1964 {
1965 floatsel[i]=(drawing==1)?c1:c2;
1966 }
1967 }
1968 }
1969 }
1970 else
1971 {
1972 unpack_tile(newtilebuf, tile, 0, false);
1973 tf_u = unpackbuf[(y<<4)+x];
1974 if(tf_u != ((drawing==1)?c1:c2))
1975 {
1976 for(int32_t i=0; i<256; i++)
1977 {
1978 if(is_in_selection(i&15,i>>4))
1979 {
1980 if(unpackbuf[i]==tf_u)
1981 {
1982 unpackbuf[i]=(drawing==1)?c1:c2;
1983 }
1984 }
1985 }
1986
1987 pack_tile(newtilebuf, unpackbuf,tile);
1988 }
1989 }
1990 ret = true;
1991 }
1992 break;
1993
1994 case t_eyedropper:
1995 if(floating_sel)
1996 memcpy(unpackbuf, floatsel, 256);
1997 else unpack_tile(newtilebuf, tile, 0, false);
1998
1999 if(gui_mouse_b()&1)
2000 {
2001 c1=unpackbuf[((y<<4)+x)];
2002 }
2003
2004 if(gui_mouse_b()&2)
2005 {
2006 c2=unpackbuf[((y<<4)+x)];
2007 }
2008 break;
2009
2010 case t_move:
2011 if((prev_x!=x)||(prev_y!=y))
2012 {
2013 if(has_selection())
2014 {
2015 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2016 wrap_sel_tile(y-prev_y, x-prev_x);
2017 shift_selection_grid(x-prev_x, y-prev_y);
2018 }
2019 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2020 prev_x=x;
2021 prev_y=y;
2022 }
2023 break;
2024
2025 case t_select:
2026 unfloat_selection();
2027 if(flip&1) x=15-x;
2028
2029 if(flip&2) y=15-y;
2030
2031 if(selecting_x1==-1||selecting_y1==-1)
2032 {
2033 selecting_x1=x;
2034 selecting_y1=y;
2035 }
2036 else
2037 {
2038 selecting_x2=x;
2039 selecting_y2=y;
2040 }
2041 break;
2042
2043 case t_wand:
2044 unfloat_selection();
2045 if(flip&1) x=15-x;
2046
2047 if(flip&2) y=15-y;
2048
2049 switch(select_mode)
2050 {
2051 case 0:
2052 clear_selection_grid();
2053 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2054 break;
2055
2056 case 1:
2057 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2058 break;
2059
2060 case 2:
2061 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2062 break;
2063
2064 case 3:
2065 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2066 break;
2067 }
2068
2069 ret = true;
2070 break;
2071 }
2072 return ret;
2073 }
2074 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2075 {
2076 popup_zqdialog_start();
2077 FONT* oldfont = font;
2078 font = get_custom_font(CFONT_DLG);
2079 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2080 status_info.yscale = text_height(font);
2081 status_info.y = 308-(status_info.h*status_info.yscale);
2082 hover_info.yscale = status_info.yscale;
2083 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2084 go();
2085 undocount = tilesize(newtilebuf[tile].format);
2086 clear_selection_grid();
2087 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2088
2089 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2090 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2091
2092 PALETTE tpal;
2093 byte oldtile[256];
2094
2095 memset(&tpal, 0, sizeof(PALETTE));
2096 memset(oldtile, 0, 256);
2097
2098 for(int32_t i=0; i<undocount; i++)
2099 {
2100 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2101 }
2102 byte undoselgrid[16][16];
2103 for(auto x = 0; x < 16; ++x)
2104 for(auto y = 0; y < 16; ++y)
2105 undoselgrid[x][y] = selection_grid[x+1][y+1];
2106 for(auto q = 0; q < 256; ++q)
2107 {
2108 floatsel[q] = 0;
2109 undofloatsel[q] = 0;
2110 floating_sel = false;
2111 undo_is_floatsel = false;
2112 }
2113
2114 int32_t tile_x=-1, tile_y=-1;
2115 int32_t temp_x=-1, temp_y=-1;
2116 bool bdown=false;
2117 int32_t done=0;
2118 drawing=0;
2119 tool_cur = -1;
2120
2121 get_palette(tpal);
2122
2123 if(newtilebuf[tile].format==tf4Bit)
2124 {
2125 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2126 }
2127 else
2128 {
2129 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2130 }
2131
2132 custom_vsync();
2133 zc_set_palette(tpal);
2134 draw_edit_scr(tile,flip,cs,oldtile, true);
2135
2136 while(gui_mouse_b())
2137 {
2138 /* do nothing */
2139 rest(1);
2140 }
2141
2142 move_origin_x=-1;
2143 move_origin_y=-1;
2144 prev_x=-1;
2145 prev_y=-1;
2146
2147
2148
2149 byte selection_pattern_source[8][8]=
2150 {
2151 {1, 1, 1, 1, 0, 0, 0, 0},
2152 {1, 1, 1, 0, 0, 0, 0, 1},
2153 {1, 1, 0, 0, 0, 0, 1, 1},
2154 {1, 0, 0, 0, 0, 1, 1, 1},
2155 {0, 0, 0, 0, 1, 1, 1, 1},
2156 {0, 0, 0, 1, 1, 1, 1, 0},
2157 {0, 0, 1, 1, 1, 1, 0, 0},
2158 {0, 1, 1, 1, 1, 0, 0, 0},
2159 };
2160
2161 byte selecting_pattern_source[8][8]=
2162 {
2163 {1, 1, 0, 0, 0, 0, 1, 1},
2164 {1, 0, 0, 0, 0, 1, 1, 1},
2165 {0, 0, 0, 0, 1, 1, 1, 1},
2166 {0, 0, 0, 1, 1, 1, 1, 0},
2167 {0, 0, 1, 1, 1, 1, 0, 0},
2168 {0, 1, 1, 1, 1, 0, 0, 0},
2169 {1, 1, 1, 1, 0, 0, 0, 0},
2170 {1, 1, 1, 0, 0, 0, 0, 1},
2171 };
2172
2173 byte intersection_pattern_source[8][8]=
2174 {
2175 {0, 0, 1, 1, 0, 0, 1, 1},
2176 {0, 1, 1, 0, 0, 1, 1, 0},
2177 {1, 1, 0, 0, 1, 1, 0, 0},
2178 {1, 0, 0, 1, 1, 0, 0, 1},
2179 {0, 0, 1, 1, 0, 0, 1, 1},
2180 {0, 1, 1, 0, 0, 1, 1, 0},
2181 {1, 1, 0, 0, 1, 1, 0, 0},
2182 {1, 0, 0, 1, 1, 0, 0, 1},
2183 };
2184
2185 selection_pattern=create_bitmap_ex(8, 8, 8);
2186
2187 for(int32_t x=0; x<8; ++x)
2188 {
2189 for(int32_t y=0; y<8; ++y)
2190 {
2191 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2192 }
2193 }
2194
2195 selecting_pattern=create_bitmap_ex(8, 8, 8);
2196
2197 for(int32_t x=0; x<8; ++x)
2198 {
2199 for(int32_t y=0; y<8; ++y)
2200 {
2201 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2202 }
2203 }
2204
2205 intersection_pattern=create_bitmap_ex(8, 8, 8);
2206
2207 for(int32_t x=0; x<8; ++x)
2208 {
2209 for(int32_t y=0; y<8; ++y)
2210 {
2211 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2212 }
2213 }
2214
2215 do
2216 {
2217 HANDLE_CLOSE_ZQDLG();
2218 if(exiting_program) break;
2219 int32_t temp_mouse_x=gui_mouse_x();
2220 int32_t temp_mouse_y=gui_mouse_y();
2221 rest(4);
2222 bool redraw=false;
2223 bool did_wand_select=false;
2224
2225 if(keypressed())
2226 {
2227 bool ctrl = CHECK_CTRL_CMD;
2228 int k = readkey()>>8;
2229 switch(k)
2230 {
2231 case KEY_F1:
2232 show_edit_tile_help();
2233 break;
2234 case KEY_ENTER_PAD:
2235 case KEY_ENTER:
2236 if(floating_sel)
2237 unfloat_selection();
2238 else done=2;
2239 break;
2240
2241 case KEY_ESC:
2242 if(floating_sel)
2243 unfloat_selection();
2244 else if(has_selection())
2245 clear_selection_grid();
2246 else done=1;
2247 break;
2248
2249 case KEY_DEL:
2250 {
2251 unpack_tile(newtilebuf, tile, 0, false);
2252 bool all = CHECK_CTRL_CMD || !has_selection();
2253 bool canDel = false;
2254 if(all)
2255 {
2256 //Check all
2257 for(auto q = 0; q < 256; ++q)
2258 if(unpackbuf[q])
2259 {
2260 canDel = true;
2261 break;
2262 }
2263 }
2264 else
2265 {
2266 //Check selection
2267 for(auto x = 0; x < 16; ++x)
2268 for(auto y = 0; y < 16; ++y)
2269 if(is_in_selection(x,y))
2270 if(unpackbuf[(y<<4)+x])
2271 {
2272 canDel = true;
2273 break;
2274 }
2275 }
2276 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2277
2278 for(int32_t i=0; i<undocount; i++)
2279 {
2280 undotile[i]=newtilebuf[tile].data[i];
2281 }
2282 for(auto x = 0; x < 16; ++x)
2283 for(auto y = 0; y < 16; ++y)
2284 undoselgrid[x][y] = selection_grid[x+1][y+1];
2285 for(auto q = 0; q < 256; ++q)
2286 undofloatsel[q] = floatsel[q];
2287 undo_is_floatsel = floating_sel;
2288
2289 if(CHECK_CTRL_CMD || !has_selection())
2290 {
2291 //Delete all
2292 for(auto q = 0; q < 256; ++q)
2293 {
2294 unpackbuf[q] = 0;
2295 floatsel[q] = 0;
2296 }
2297 }
2298 else
2299 {
2300 //Delete selection
2301 for(auto x = 0; x < 16; ++x)
2302 for(auto y = 0; y < 16; ++y)
2303 {
2304 if(floating_sel)
2305 {
2306 floatsel[x+(y<<4)] = 0;
2307 }
2308 else if(is_in_selection(x,y))
2309 {
2310 unpackbuf[(y<<4)+x] = 0;
2311 }
2312 }
2313 }
2314 pack_tile(newtilebuf, unpackbuf, tile);
2315 redraw=true;
2316 }
2317 break;
2318
2319 case KEY_A:
2320 clear_selection_grid();
2321 invert_selection_grid();
2322 redraw=true;
2323 break;
2324
2325 case KEY_D:
2326 clear_selection_grid();
2327 redraw=true;
2328 break;
2329
2330 case KEY_I:
2331 invert_selection_grid();
2332 redraw=true;
2333 break;
2334
2335 case KEY_H:
2336 flip^=1;
2337 normalize(tile,tile,0,flip);
2338 flip=0;
2339 redraw=true;
2340 break;
2341
2342 case KEY_V:
2343 flip^=2;
2344 normalize(tile,tile,0,flip);
2345 flip=0;
2346 redraw=true;
2347 break;
2348
2349 case KEY_F12:
2350 onSnapshot();
2351 break;
2352
2353 case KEY_R:
2354 {
2355 //if(CHECK_CTRL_CMD))
2356 // {
2357 //do_recolor(tile); redraw=true; saved=false;
2358 // }
2359 //else
2360 // {
2361 go_tiles();
2362 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2363 redraw=true;
2364 saved=false;
2365 break;
2366 }
2367
2368 case KEY_EQUALS:
2369 case KEY_PLUS_PAD:
2370 {
2371 if(CHECK_CTRL_CMD ||
2372 key[KEY_ALT] || key[KEY_ALTGR])
2373 {
2374 for(int32_t i=0; i<undocount; i++)
2375 undotile[i]=newtilebuf[tile].data[i];
2376 for(auto x = 0; x < 16; ++x)
2377 for(auto y = 0; y < 16; ++y)
2378 undoselgrid[x][y] = selection_grid[x+1][y+1];
2379 for(auto q = 0; q < 256; ++q)
2380 undofloatsel[q] = floatsel[q];
2381 undo_is_floatsel = floating_sel;
2382
2383 if(key[KEY_ALT] || key[KEY_ALTGR])
2384 shift_tile_colors(tile, 16, false);
2385 else
2386 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2387 }
2388 else
2389 cs = (cs<13) ? cs+1:0;
2390
2391 redraw=true;
2392 break;
2393 }
2394
2395 case KEY_MINUS:
2396 case KEY_MINUS_PAD:
2397 {
2398 if(CHECK_CTRL_CMD ||
2399 key[KEY_ALT] || key[KEY_ALTGR])
2400 {
2401 for(int32_t i=0; i<undocount; i++)
2402 undotile[i]=newtilebuf[tile].data[i];
2403 for(auto x = 0; x < 16; ++x)
2404 for(auto y = 0; y < 16; ++y)
2405 undoselgrid[x][y] = selection_grid[x+1][y+1];
2406 for(auto q = 0; q < 256; ++q)
2407 undofloatsel[q] = floatsel[q];
2408 undo_is_floatsel = floating_sel;
2409
2410 if(key[KEY_ALT] || key[KEY_ALTGR])
2411 shift_tile_colors(tile, -16, false);
2412 else
2413 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2414 }
2415 else
2416 cs = (cs>0) ? cs-1:13;
2417
2418 redraw=true;
2419 break;
2420 }
2421
2422 case KEY_SPACE:
2423 gridmode=(gridmode+1)%gm_max;
2424 redraw=true;
2425 break;
2426
2427 case KEY_Z:
2428 if(!ctrl)
2429 break;
2430 //Ctrl+Z == undo
2431 [[fallthrough]];
2432 case KEY_U:
2433 for(int32_t i=0; i<undocount; i++)
2434 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2435
2436 for(auto x = 0; x < 16; ++x)
2437 for(auto y = 0; y < 16; ++y)
2438 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2439
2440 for(auto q = 0; q < 256; ++q)
2441 zc_swap(undofloatsel[q], floatsel[q]);
2442 zc_swap(undo_is_floatsel, floating_sel);
2443
2444 redraw=true;
2445 break;
2446
2447 case KEY_S:
2448 if(CHECK_CTRL_CMD)
2449 {
2450 for(int32_t i=0; i<undocount; i++)
2451 {
2452 undotile[i]=newtilebuf[tile].data[i];
2453 }
2454 for(auto x = 0; x < 16; ++x)
2455 for(auto y = 0; y < 16; ++y)
2456 undoselgrid[x][y] = selection_grid[x+1][y+1];
2457 for(auto q = 0; q < 256; ++q)
2458 undofloatsel[q] = floatsel[q];
2459 undo_is_floatsel = floating_sel;
2460
2461 unpack_tile(newtilebuf, tile, 0, false);
2462
2463 if(has_selection())
2464 {
2465 for(int32_t i=0; i<256; i++)
2466 {
2467 if(!is_in_selection(i%16,i/16))
2468 continue;
2469 if(unpackbuf[i]==c1)
2470 {
2471 unpackbuf[i]=c2;
2472 }
2473 else if(unpackbuf[i]==c2)
2474 {
2475 unpackbuf[i]=c1;
2476 }
2477 if(floating_sel)
2478 {
2479 if(floatsel[i]==c1)
2480 {
2481 floatsel[i]=c2;
2482 }
2483 else if(floatsel[i]==c2)
2484 {
2485 floatsel[i]=c1;
2486 }
2487 }
2488 }
2489 }
2490 else
2491 {
2492 for(int32_t i=0; i<256; i++)
2493 {
2494 if(unpackbuf[i]==c1)
2495 {
2496 unpackbuf[i]=c2;
2497 }
2498 else if(unpackbuf[i]==c2)
2499 {
2500 unpackbuf[i]=c1;
2501 }
2502 }
2503 }
2504
2505 pack_tile(newtilebuf, unpackbuf,tile);
2506 }
2507
2508 zc_swap(c1,c2);
2509 redraw=true;
2510 break;
2511
2512 case KEY_UP:
2513 if(CHECK_CTRL_CMD)
2514 {
2515 unfloat_selection();
2516 tile=zc_max(0,tile-TILES_PER_ROW);
2517 undocount = tilesize(newtilebuf[tile].format);
2518
2519 for(int32_t i=0; i<undocount; i++)
2520 {
2521 undotile[i]=newtilebuf[tile].data[i];
2522 oldtile[i]=undotile[i];
2523 }
2524
2525 redraw=true;
2526 }
2527 else
2528 {
2529 for(int32_t i=0; i<undocount; i++)
2530 {
2531 undotile[i]=newtilebuf[tile].data[i];
2532 }
2533 for(auto x = 0; x < 16; ++x)
2534 for(auto y = 0; y < 16; ++y)
2535 undoselgrid[x][y] = selection_grid[x+1][y+1];
2536 for(auto q = 0; q < 256; ++q)
2537 undofloatsel[q] = floatsel[q];
2538 undo_is_floatsel = floating_sel;
2539 if(has_selection())
2540 {
2541 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2542 wrap_sel_tile(-1, 0);
2543 shift_selection_grid(0, -1);
2544 }
2545 else wrap_tile(tile, -1, 0, false);
2546 redraw=true;
2547 }
2548 break;
2549
2550 case KEY_DOWN:
2551 if(CHECK_CTRL_CMD)
2552 {
2553 unfloat_selection();
2554 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2555 undocount = tilesize(newtilebuf[tile].format);
2556
2557 for(int32_t i=0; i<undocount; i++)
2558 {
2559 undotile[i]=newtilebuf[tile].data[i];
2560 oldtile[i]=undotile[i];
2561 }
2562
2563 redraw=true;
2564 }
2565 else
2566 {
2567 for(int32_t i=0; i<undocount; i++)
2568 {
2569 undotile[i]=newtilebuf[tile].data[i];
2570 }
2571 for(auto x = 0; x < 16; ++x)
2572 for(auto y = 0; y < 16; ++y)
2573 undoselgrid[x][y] = selection_grid[x+1][y+1];
2574 for(auto q = 0; q < 256; ++q)
2575 undofloatsel[q] = floatsel[q];
2576 undo_is_floatsel = floating_sel;
2577 if(has_selection())
2578 {
2579 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2580 wrap_sel_tile(1, 0);
2581 shift_selection_grid(0, 1);
2582 }
2583 else wrap_tile(tile, 1, 0, false);
2584 redraw=true;
2585 }
2586 break;
2587
2588 case KEY_LEFT:
2589 if(CHECK_CTRL_CMD)
2590 {
2591 unfloat_selection();
2592 tile=zc_max(0,tile-1);
2593 undocount = tilesize(newtilebuf[tile].format);
2594
2595 for(int32_t i=0; i<undocount; i++)
2596 {
2597 undotile[i]=newtilebuf[tile].data[i];
2598 oldtile[i]=undotile[i];
2599 }
2600
2601 redraw=true;
2602 }
2603 else
2604 {
2605 for(int32_t i=0; i<undocount; i++)
2606 {
2607 undotile[i]=newtilebuf[tile].data[i];
2608 }
2609 for(auto x = 0; x < 16; ++x)
2610 for(auto y = 0; y < 16; ++y)
2611 undoselgrid[x][y] = selection_grid[x+1][y+1];
2612 for(auto q = 0; q < 256; ++q)
2613 undofloatsel[q] = floatsel[q];
2614 undo_is_floatsel = floating_sel;
2615 if(has_selection())
2616 {
2617 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2618 wrap_sel_tile(0, -1);
2619 shift_selection_grid(-1, 0);
2620 }
2621 else wrap_tile(tile, 0, -1, false);
2622 redraw=true;
2623 }
2624 break;
2625
2626 case KEY_RIGHT:
2627 if(CHECK_CTRL_CMD)
2628 {
2629 unfloat_selection();
2630 tile=zc_min(tile+1, NEWMAXTILES-1);
2631 undocount = tilesize(newtilebuf[tile].format);
2632
2633 for(int32_t i=0; i<undocount; i++)
2634 {
2635 undotile[i]=newtilebuf[tile].data[i];
2636 oldtile[i]=undotile[i];
2637 }
2638
2639 redraw=true;
2640 }
2641 else
2642 {
2643 for(int32_t i=0; i<undocount; i++)
2644 {
2645 undotile[i]=newtilebuf[tile].data[i];
2646 }
2647 for(auto x = 0; x < 16; ++x)
2648 for(auto y = 0; y < 16; ++y)
2649 undoselgrid[x][y] = selection_grid[x+1][y+1];
2650 for(auto q = 0; q < 256; ++q)
2651 undofloatsel[q] = floatsel[q];
2652 undo_is_floatsel = floating_sel;
2653 if(has_selection())
2654 {
2655 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2656 wrap_sel_tile(0, 1);
2657 shift_selection_grid(1, 0);
2658 }
2659 else wrap_tile(tile, 0, 1, false);
2660 redraw=true;
2661 }
2662 break;
2663 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2664 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2665 case KEY_8: case KEY_9:
2666 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2667 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2668 case KEY_8_PAD: case KEY_9_PAD:
2669 {
2670 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2671 if(unsigned(t) < t_max)
2672 {
2673 if(old_tool != -1)
2674 old_tool = t;
2675 else tool = t;
2676 }
2677 break;
2678 }
2679 case KEY_TAB:
2680 {
2681 if(key_shifts & KB_CTRL_FLAG)
2682 {
2683 xmode = (xmode+1)%XMODE_MAX;
2684 if(!xmode)
2685 bgmode = (bgmode+1)%BGMODE_MAX;
2686 }
2687 else if(key_shifts & KB_SHIFT_FLAG)
2688 hide_grid = !hide_grid;
2689 else show_quartgrid = !show_quartgrid;
2690 redraw = true;
2691 break;
2692 }
2693 }
2694 clear_keybuf();
2695 }
2696
2697 if(!gui_mouse_b())
2698 {
2699 if(is_selecting())
2700 {
2701 unfloat_selection();
2702 int32_t x1=zc_min(selecting_x1,selecting_x2);
2703 int32_t x2=zc_max(selecting_x1,selecting_x2);
2704 int32_t y1=zc_min(selecting_y1,selecting_y2);
2705 int32_t y2=zc_max(selecting_y1,selecting_y2);
2706
2707 if(select_mode==0)
2708 {
2709 clear_selection_grid();
2710 }
2711
2712 for(int32_t x=x1; x<=x2; ++x)
2713 {
2714 for(int32_t y=y1; y<=y2; ++y)
2715 {
2716 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2717 }
2718 }
2719
2720 if(select_mode==3)
2721 {
2722 for(int32_t y=0; y<16; ++y)
2723 {
2724 for(int32_t x=0; x<x1; ++x)
2725 {
2726 selection_grid[x+1][y+1]=0;
2727 }
2728
2729 for(int32_t x=x2+1; x<16; ++x)
2730 {
2731 selection_grid[x+1][y+1]=0;
2732 }
2733 }
2734
2735 for(int32_t x=x1; x<=x2; ++x)
2736 {
2737 for(int32_t y=0; y<y1; ++y)
2738 {
2739 selection_grid[x+1][y+1]=0;
2740 }
2741
2742 for(int32_t y=y2+1; y<16; ++y)
2743 {
2744 selection_grid[x+1][y+1]=0;
2745 }
2746 }
2747 }
2748 }
2749
2750 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2751 did_wand_select=false;
2752 }
2753
2754 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2755 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2756 bool ctrl=CHECK_CTRL_CMD;
2757 static int32_t last_tool_val = 0;
2758
2759 if(tool==t_select||tool==t_wand)
2760 {
2761 if(!drawing)
2762 {
2763 int32_t type=0;
2764
2765 if(has_selection())
2766 {
2767 if(shift)
2768 {
2769 type+=1;
2770 }
2771
2772 if(alt)
2773 {
2774 type+=2;
2775 }
2776 }
2777
2778 if(type!=select_mode)
2779 {
2780 select_mode=type;
2781
2782 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2783 set_tool_sprite(tool,type);
2784 }
2785 }
2786 }
2787 else if(alt||ctrl)
2788 {
2789 if(old_tool==-1)
2790 {
2791 old_tool = tool;
2792 tool_cur = -1;
2793 }
2794 if(alt&&ctrl)
2795 tool = t_recolor;
2796 else if(alt)
2797 tool = t_eyedropper;
2798 else tool = t_fill;
2799 }
2800 else if(old_tool!=-1)
2801 {
2802 tool = old_tool;
2803 old_tool = -1;
2804 tool_cur = -1;
2805 redraw = true;
2806 }
2807 if(last_tool_val != tool)
2808 {
2809 redraw = true;
2810 tool_cur = -1;
2811 update_tool_cursor();
2812 last_tool_val = tool;
2813 }
2814
2815 if(!bdown)
2816 {
2817 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2818 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2819 }
2820
2821 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2822 {
2823 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2824 {
2825 if(tool==t_move || tool==t_fill)
2826 {
2827 set_tool_sprite(tool,1);
2828
2829 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2830 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2831 }
2832
2833 for(int32_t i=0; i<undocount; i++)
2834 {
2835 undotile[i]=newtilebuf[tile].data[i];
2836 }
2837 for(auto x = 0; x < 16; ++x)
2838 for(auto y = 0; y < 16; ++y)
2839 undoselgrid[x][y] = selection_grid[x+1][y+1];
2840 for(auto q = 0; q < 256; ++q)
2841 undofloatsel[q] = floatsel[q];
2842 undo_is_floatsel = floating_sel;
2843
2844 drawing=1;
2845 }
2846
2847 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2848 {
2849 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2850 {
2851 done=2;
2852 }
2853 }
2854
2855 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2856 {
2857 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2858 {
2859 done=1;
2860 }
2861 }
2862
2863 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2866 {
2867 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2868 get_palette(tpal);
2869
2870 if(newtilebuf[tile].format==tf4Bit)
2871 {
2872 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2873 }
2874 else
2875 {
2876 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2877 }
2878
2879 redraw=true;
2880 }
2881 }
2882
2883 int sqr_clicked;
2884 if(show_quartgrid && qgrid_tool(tool))
2885 {
2886 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2887 if(sqr_clicked > -1)
2888 {
2889 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2890 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2891 refl_flags ^= (1<<sqr_clicked);
2892 }
2893 }
2894 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2895 if(sqr_clicked > -1)
2896 {
2897 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2898 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2899 xmode = sqr_clicked;
2900 }
2901 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2902 if(sqr_clicked > -1)
2903 {
2904 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2905 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2906 bgmode = sqr_clicked;
2907 }
2908
2909 if(showcolortip)
2910 {
2911 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2912 {
2913 showcolortip = 0;
2914 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2915 }
2916 }
2917 else
2918 {
2919 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2920 {
2921 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2922 {
2923 showcolortip = 1;
2924 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2925 redraw=true;
2926 }
2927 }
2928 }
2929
2930 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2933 {
2934 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2935 redraw=true;
2936 }
2937 }
2938 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2939 {
2940 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2941 redraw=true;
2942 }
2943 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2944 {
2945 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2946 redraw=true;
2947 }
2948
2949 switch(newtilebuf[tile].format)
2950 {
2951 case tf4Bit:
2952 {
2953 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2954 if(ind > -1)
2955 {
2956 c1 = ind;
2957 redraw=true;
2958 }
2959 break;
2960 }
2961 case tf8Bit:
2962 {
2963 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2964 if(ind > -1)
2965 {
2966 c1 = ind;
2967 redraw=true;
2968 }
2969 break;
2970 }
2971 }
2972
2973
2974 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2975 if(newtool > -1 && newtool < t_max)
2976 {
2977 tool=newtool;
2978 redraw=true;
2979 }
2980
2981 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2982 {
2983 if(do_x_button(screen, x_btn.x, x_btn.y))
2984 {
2985 done=1;
2986 }
2987 }
2988 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2989 {
2990 if(do_question_button(screen, info_btn.x, info_btn.y))
2991 {
2992 show_edit_tile_help();
2993 }
2994 }
2995
2996 bdown=true;
2997 }
2998
2999 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3000 {
3001 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3002 {
3003 if(tool==t_move || tool==t_fill)
3004 {
3005 set_tool_sprite(tool,1);
3006
3007 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3008 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3009 }
3010
3011 for(int32_t i=0; i<undocount; i++)
3012 {
3013 undotile[i]=newtilebuf[tile].data[i];
3014 }
3015 for(auto x = 0; x < 16; ++x)
3016 for(auto y = 0; y < 16; ++y)
3017 undoselgrid[x][y] = selection_grid[x+1][y+1];
3018 for(auto q = 0; q < 256; ++q)
3019 undofloatsel[q] = floatsel[q];
3020 undo_is_floatsel = floating_sel;
3021
3022 drawing=2;
3023 }
3024
3025 switch(newtilebuf[tile].format)
3026 {
3027 case tf4Bit:
3028 {
3029 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3030 if(ind > -1)
3031 {
3032 c2 = ind;
3033 redraw=true;
3034 }
3035 break;
3036 }
3037 case tf8Bit:
3038 {
3039 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3040 if(ind > -1)
3041 {
3042 c2 = ind;
3043 redraw=true;
3044 }
3045 break;
3046 }
3047 }
3048
3049 bdown=true;
3050 }
3051
3052 if(bdown&&!gui_mouse_b()) //released the buttons
3053 {
3054 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3055 {
3056 if(tool==t_move || tool==t_fill)
3057 {
3058 set_tool_sprite(tool,0);
3059 }
3060 }
3061 }
3062
3063 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3064 {
3065 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3066 int32_t x=ind%zoomtile.w;
3067 int32_t y=ind/zoomtile.w;
3068
3069 bool reset_draw = false;
3070
3071 if(__pixel_draw(x,y,tile,flip))
3072 reset_draw = true;
3073 if(show_quartgrid)
3074 {
3075 auto tmp_sel_mode = select_mode;
3076 if(tool == t_wand && select_mode == 0)
3077 select_mode = 1;
3078 if(qgrid_tool(tool))
3079 {
3080 if(refl_flags & (1<<REFL_HFLIP))
3081 if(__pixel_draw(15-x,y,tile,flip))
3082 reset_draw = true;
3083 if(refl_flags & (1<<REFL_VFLIP))
3084 if(__pixel_draw(x,15-y,tile,flip))
3085 reset_draw = true;
3086 //Diagonal flip and 180° rotation are the same!
3087 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3088 if(__pixel_draw(15-x,15-y,tile,flip))
3089 reset_draw = true;
3090 if(refl_flags & (1<<REFL_90CW))
3091 if(__pixel_draw(15-y,x,tile,flip))
3092 reset_draw = true;
3093 if(refl_flags & (1<<REFL_90CCW))
3094 if(__pixel_draw(y,15-x,tile,flip))
3095 reset_draw = true;
3096 }
3097 select_mode = tmp_sel_mode;
3098 }
3099
3100 if(reset_draw)
3101 drawing = 0;
3102 redraw=true;
3103 }
3104
3105 if(gui_mouse_b()==0)
3106 {
3107 bdown=false;
3108 drawing=0;
3109 }
3110
3111 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3112 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3113
3114 {
3115 tile_x=temp_x;
3116 tile_y=temp_y;
3117 redraw=true;
3118 }
3119
3120 const char *toolnames[t_max]=
3121 {
3122 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3123 };
3124
3125 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3126 if(toolbtn > -1 && toolbtn < t_max)
3127 {
3128 int32_t column = toolbtn%tool_btns.w;
3129 int32_t row = toolbtn/tool_btns.w;
3130
3131 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3132 redraw=true;
3133 }
3134 /* Highlight the hovered pixel? Eh, maybe too much?
3135 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3136 if(hov_pix > -1)
3137 {
3138 int32_t column = hov_pix%zoomtile.w;
3139 int32_t row = hov_pix/zoomtile.w;
3140
3141 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3142 redraw=true;
3143 }*/
3144
3145 if(redraw)
3146 {
3147 custom_vsync();
3148 draw_edit_scr(tile,flip,cs,oldtile, false);
3149 }
3150 else
3151 {
3152 bool hs=has_selection();
3153
3154 if(hs)
3155 {
3156 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3157 }
3158
3159 custom_vsync();
3160
3161 if(hs)
3162 {
3163 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3164 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3165 }
3166
3167 update_tool_cursor();
3168 SCRFIX();
3169 }
3170
3171 }
3172 while(!done);
3173
3174 unfloat_selection();
3175 clear_selection_grid();
3176
3177 while(gui_mouse_b())
3178 {
3179 /* do nothing */
3180 rest(1);
3181 }
3182
3183 if(done==1)
3184 {
3185 for(int32_t i=0; i<undocount; i++)
3186 {
3187 newtilebuf[tile].data[i]=oldtile[i];
3188 }
3189 }
3190 else
3191 {
3192 byte *buf = new byte[undocount];
3193
3194 // put back old tile
3195 for(int32_t i=0; i<undocount; i++)
3196 {
3197 buf[i] = newtilebuf[tile].data[i];
3198 newtilebuf[tile].data[i] = oldtile[i];
3199 }
3200
3201 // go
3202 go_tiles();
3203
3204 // replace old tile with new one again
3205 for(int32_t i=0; i<undocount; i++)
3206 {
3207 newtilebuf[tile].data[i] = buf[i];
3208 }
3209
3210 // usetiles=true;
3211 saved=false;
3212
3213 if(buf!=NULL)
3214 {
3215 delete[] buf;
3216 }
3217 }
3218
3219 MouseSprite::set(ZQM_NORMAL);
3220 register_blank_tiles();
3221 register_used_tiles();
3222 clear_tooltip();
3223 comeback();
3224 destroy_bitmap(selection_pattern);
3225 destroy_bitmap(selecting_pattern);
3226 destroy_bitmap(intersection_pattern);
3227 font = oldfont;
3228 popup_zqdialog_end();
3229 }
3230
3231 /* Grab Tile Code */
3232
3233 enum recolorState { rcNone, rc4Bit, rc8Bit };
3234
3235 BITMAP* original_imagebuf_bitmap=NULL;
3236 void *imagebuf=NULL;
3237 int32_t imagebuf_bitmap_scale=0;
3238 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3239 int32_t imagesize=0;
3240 int32_t tilecount=0;
3241 int32_t imagetype=0;
3242 int32_t imagex,imagey,selx,sely;
3243 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3244 bool nesmode=false;
3245 int32_t grabmask=0;
3246 recolorState recolor=rcNone;
3247 PALETTE imagepal;
3248
3249 /* bestfit_color:
3250 * Searches a palette for the color closest to the requested R, G, B value.
3251 */
3252 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3253 {
3254 int32_t bestMatch = 0; // Color with the lowest total difference so far
3255 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3256 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3257
3258 for(int32_t i = 0; i < CSET_SIZE; i++)
3259 {
3260 byte *rgbByte;
3261
3262 // This seems to be right...
3263 if(cs==2 || cs==3 || cs==4)
3264 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3265 else if(cs==9)
3266 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3267 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3268 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3269 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3270 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3271 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3272 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3273 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3274 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3275 else
3276 rgbByte = colordata + (CSET(cs)+i)*3;
3277
3278 int32_t dr=r-*rgbByte;
3279 int32_t dg=g-*(rgbByte+1);
3280 int32_t db=b-*(rgbByte+2);
3281
3282 // Track both the total color difference and the single greatest
3283 // difference of R, G, B. The idea is that it's better to have
3284 // two or three small differences than one big one.
3285 // The differences are multiplied by different numbers to account
3286 // for the differences in perceived brightness of the three colors.
3287 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3288 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3289
3290 // Perfect match? Just stop here.
3291 if(totalDiff==0)
3292 return i;
3293
3294 if(totalDiff < bestTotalDiff || // Best match so far?
3295 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3296 {
3297 bestMatch=i;
3298 bestTotalDiff=totalDiff;
3299 bestHighDiff=highDiff;
3300 }
3301 }
3302
3303 return bestMatch;
3304 }
3305
3306 // Same as the above, but draws from all colors in CSets 0-11.
3307 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3308 {
3309 int32_t bestMatch = 0;
3310 float bestTotalDiff = 100000;
3311 float bestHighDiff = 100000;
3312
3313 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3314 {
3315 byte *rgbByte;
3316
3317 int32_t cs=i>>4;
3318 if(cs==2 || cs==3 || cs==4)
3319 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3320 else if(cs==9)
3321 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3322 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3323 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3324 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3325 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3326 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3327 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3328 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3329 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3330 else
3331 rgbByte = colordata + i * 3;
3332
3333 int32_t dr=r-*rgbByte;
3334 int32_t dg=g-*(rgbByte+1);
3335 int32_t db=b-*(rgbByte+2);
3336
3337 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3338 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3339
3340 if(totalDiff==0) // Perfect match?
3341 return i;
3342
3343 if(totalDiff < bestTotalDiff || // Best match so far?
3344 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3345 {
3346 bestMatch=i;
3347 bestTotalDiff=totalDiff;
3348 bestHighDiff=highDiff;
3349 }
3350 }
3351
3352 return bestMatch;
3353 }
3354
3355 byte cset_reduce_table[PAL_SIZE];
3356
3357 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3358 {
3359 for(int32_t i=0; i<PAL_SIZE; i++)
3360 {
3361 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3362 }
3363 }
3364
3365 void calc_cset_reduce_table_8bit(PALETTE pal)
3366 {
3367 for(int32_t i=0; i<PAL_SIZE; i++)
3368 {
3369 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3370 }
3371 }
3372
3373 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3374 {
3375 //storage space for the grabbed image
3376 byte buf[64];
3377 memset(buf,0,64);
3378 byte *oldsrc=src;
3379
3380 //for 8 lines in the source image...
3381 for(int32_t line=0; line<(nesmode?4:8); line++)
3382 {
3383 //bx is the pixel at the start of a line in the storage buffer
3384 int32_t bx=line<<(nesmode?4:3);
3385 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3386 byte b=src[(bp&1)?line:line<<1];
3387
3388 //fill the storage buffer with data from the source image
3389 for(int32_t i=7; i>=0; --i)
3390 {
3391 buf[bx+i] = (b&1)+(cs<<4);
3392 b>>=1;
3393 }
3394 }
3395
3396 ++src;
3397
3398 for(int32_t p=1; p<bp; p++)
3399 {
3400 for(int32_t line=0; line<(nesmode?4:8); line++)
3401 {
3402 int32_t bx=line<<(nesmode?4:3);
3403 byte b=src[(bp&1)?line:line<<1];
3404
3405 for(int32_t i=7; i>=0; --i)
3406 {
3407 if(nesmode)
3408 {
3409 buf[bx+8+i] = (b&1)+(cs<<4);
3410 }
3411 else
3412 {
3413 buf[bx+i] |= (b&1)<<p;
3414 }
3415
3416 b>>=1;
3417 }
3418 }
3419
3420 if(p&1)
3421 {
3422 src+=15;
3423 }
3424 else
3425 {
3426 ++src;
3427 }
3428 }
3429
3430
3431 if(nesmode)
3432 {
3433 src=oldsrc;
3434
3435 for(int32_t counter=0; counter<2; ++counter, ++src)
3436 {
3437 //for 8 lines in the source image...
3438 for(int32_t line=0; line<4; line++)
3439 {
3440 //bx is the pixel at the start of a line in the storage buffer
3441 int32_t bx=line<<4;
3442 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3443 byte b=src[(line+4)<<1];
3444
3445 //fill the storage buffer with data from the source image
3446 for(int32_t i=7; i>=0; --i)
3447 {
3448 // buf[bx+i] = (b&1)+(cs<<4);
3449 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3450 b>>=1;
3451 }
3452 }
3453 }
3454 }
3455
3456 int32_t c=0;
3457
3458 switch(romtilemode)
3459 {
3460 case 0:
3461 case 1:
3462 case 2:
3463 for(int32_t j=0; j<8; j++)
3464 {
3465 for(int32_t i=0; i<8; i++)
3466 {
3467 putpixel(dest,x+i,y+j,buf[c++]);
3468 }
3469 }
3470
3471 break;
3472
3473 case 3:
3474 for(int32_t j=0; j<4; j++)
3475 {
3476 for(int32_t i=0; i<16; i++)
3477 {
3478 putpixel(dest,x+i,y+j,buf[c++]);
3479 }
3480 }
3481
3482 break;
3483 }
3484 }
3485
3486 const char *file_type[ftMAX]=
3487 {
3488 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3489 };
3490
3491 void draw_grab_window()
3492 {
3493 int w = 640;
3494 int h = 480;
3495 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3496 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3497 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3498 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3499
3500 FONT *oldfont = font;
3501 font = get_zc_font(font_lfont);
3502 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3503 font=oldfont;
3504 }
3505
3506 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3507 {
3508 width=width;
3509 height=height;
3510 white=white; // happy birthday compiler
3511
3512 int32_t yofs=0;
3513 //clear_to_color(screen2,bg);
3514 rectfill(screen2, 0, 0, 319, 159, black);
3515 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3516 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3517 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3518 yofs=3;
3519
3520 // text_mode(-1);
3521 int32_t tileromcolumns=20;
3522
3523 switch(imagetype)
3524 {
3525 case ftBMP:
3526 if(recolor==rcNone)
3527 {
3528 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3529 }
3530 else
3531 {
3532 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3533 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3534
3535 for(int32_t y=0; y<maxy; y++)
3536 {
3537 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3538 {
3539 break;
3540 }
3541
3542 for(int32_t x=0; x<maxx; x++)
3543 {
3544 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3545 {
3546 break;
3547 }
3548
3549 if(recolor==rc8Bit)
3550 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3551 else
3552 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3553 }
3554 }
3555 }
3556
3557 break;
3558
3559 case ftZGP:
3560 case ftQST:
3561 case ftZQT:
3562 case ftQSU:
3563 case ftTIL:
3564 {
3565 tiledata *hold = newtilebuf;
3566 newtilebuf = grabtilebuf;
3567 //fixme
3568 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3569 int32_t t=imagey*TILES_PER_ROW;
3570
3571 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3572 {
3573 if(t <= tilecount)
3574 {
3575 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3576 }
3577
3578 ++t;
3579 }
3580
3581 newtilebuf = hold;
3582 //fixme
3583 }
3584 break;
3585
3586 case ftBIN:
3587 {
3588 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3589 byte *buf = (byte*)imagebuf;
3590
3591 switch(romtilemode)
3592 {
3593 case 0:
3594 for(int32_t y=0; y<160; y+=8)
3595 {
3596 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3597 {
3598 puttileROM(screen2,x,y,buf+ofs,cs);
3599 ofs+=8*bp;
3600 }
3601 }
3602
3603 for(int32_t y=0; y<160; y+=8)
3604 {
3605 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3606 {
3607 puttileROM(screen2,x+128,y,buf+ofs,cs);
3608 ofs+=8*bp;
3609 }
3610 }
3611
3612 break;
3613
3614 case 1:
3615 for(int32_t y=0; y<160; y+=16)
3616 {
3617 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3618 {
3619 puttileROM(screen2,x,y,buf+ofs,cs);
3620 ofs+=8*bp;
3621 puttileROM(screen2,x,y+8,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=16)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3633 ofs+=8*bp;
3634 }
3635 }
3636
3637 break;
3638
3639 case 2:
3640 for(int32_t y=0; y<160; y+=16)
3641 {
3642 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3643 {
3644 puttileROM(screen2,x,y,buf+ofs,cs);
3645 ofs+=8*bp;
3646 puttileROM(screen2,x+8,y,buf+ofs,cs);
3647 ofs+=8*bp;
3648 puttileROM(screen2,x,y+8,buf+ofs,cs);
3649 ofs+=8*bp;
3650 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3651 ofs+=8*bp;
3652 }
3653 }
3654
3655 for(int32_t y=0; y<160; y+=16)
3656 {
3657 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3658 {
3659 puttileROM(screen2,x+128,y,buf+ofs,cs);
3660 ofs+=8*bp;
3661 puttileROM(screen2,x+136,y,buf+ofs,cs);
3662 ofs+=8*bp;
3663 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3664 ofs+=8*bp;
3665 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3666 ofs+=8*bp;
3667 }
3668 }
3669
3670 break;
3671
3672 case 3:
3673 for(int32_t y=0; y<160; y+=16)
3674 {
3675 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3676 {
3677 puttileROM(screen2,x,y,buf+ofs,cs);
3678 ofs+=8*bp;
3679 puttileROM(screen2,x,y+4,buf+ofs,cs);
3680 ofs+=8*bp;
3681 puttileROM(screen2,x,y+8,buf+ofs,cs);
3682 ofs+=8*bp;
3683 puttileROM(screen2,x,y+12,buf+ofs,cs);
3684 ofs+=8*bp;
3685 }
3686 }
3687
3688 for(int32_t y=0; y<160; y+=16)
3689 {
3690 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3691 {
3692 puttileROM(screen2,x+128,y,buf+ofs,cs);
3693 ofs+=8*bp;
3694 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3695 ofs+=8*bp;
3696 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3697 ofs+=8*bp;
3698 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3699 ofs+=8*bp;
3700 }
3701 }
3702
3703 break;
3704 }
3705 }
3706 break;
3707 }
3708
3709 tiledata hold;
3710 bool holdblank = blank_tile_table[0];
3711
3712 if(is_valid_format(newtilebuf[0].format))
3713 {
3714 hold.format = newtilebuf[0].format;
3715 hold.data = (byte *)malloc(tilesize(hold.format));
3716 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3717 }
3718 else
3719 {
3720 hold.format=tfInvalid;
3721 hold.data=NULL;
3722 }
3723
3724 newtilebuf[0].format=newformat[0];
3725 blank_tile_table[0] = false;
3726
3727 if(newtilebuf[0].data!=NULL)
3728 {
3729 free(newtilebuf[0].data);
3730 }
3731
3732 if(is_valid_format(newtilebuf[0].format))
3733 {
3734 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3735
3736 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3737 {
3738 newtilebuf[0].data[i]=newtile[i];
3739 }
3740 }
3741 else
3742 {
3743 newtilebuf[0].data=NULL;
3744 }
3745
3746 puttile16(screen2,0,208,168+yofs,cs,0);
3747 overtile16(screen2,0,232,168+yofs,cs,0);
3748 newtilebuf[0].format=hold.format;
3749 blank_tile_table[0] = holdblank;
3750
3751 if(newtilebuf[0].data!=NULL)
3752 {
3753 free(newtilebuf[0].data);
3754 }
3755
3756 if(is_valid_format(newtilebuf[0].format))
3757 {
3758 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3759
3760 for(int32_t i=0; i<256; i++)
3761 {
3762 newtilebuf[0].data[i]=hold.data[i];
3763 }
3764 }
3765 else
3766 {
3767 newtilebuf[0].data=NULL;
3768 }
3769
3770 if(hold.data!=NULL)
3771 {
3772 free(hold.data);
3773 }
3774
3775 puttile16(screen2,tile,208,192+yofs,cs,0);
3776 overtile16(screen2,tile,232,192+yofs,cs,0);
3777
3778 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3779 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3780 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3781 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3782
3783 // rect(screen2,183,167,200,184,dvc(7*2));
3784 // rect(screen2,207,167,224,184,dvc(7*2));
3785 // rect(screen2,231,167,248,184,dvc(7*2));
3786 // rect(screen2,207,191,224,208,dvc(7*2));
3787 // rect(screen2,231,191,248,208,dvc(7*2));
3788
3789 /*
3790 rect(screen2,183,167,200,184,vc(14));
3791 rect(screen2,207,167,224,184,vc(14));
3792 rect(screen2,231,167,248,184,vc(14));
3793 rect(screen2,207,191,224,208,vc(14));
3794 rect(screen2,231,191,248,208,vc(14));
3795 */
3796 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3797 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3798 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3801 int32_t screen_xofs=6;
3802 int32_t screen_yofs=25;
3803 int winh = 511;
3804 int32_t mul = 2;
3805
3806 yofs=16;
3807
3808 custom_vsync();
3809
3810 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3811
3812 // Suspend the current font while draw_text_button does its work
3813 FONT* oldfont = font;
3814
3815 font = get_zc_font(font_lfont_l);
3816
3817 int txt_x = 8*mul;
3818 int rbtn_x = 255*mul;
3819 int max_fpath_wid = rbtn_x-2-txt_x;
3820 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3821 // Interface
3822 switch(imagetype)
3823 {
3824 case 0:
3825 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3826 break;
3827
3828 case ftBMP:
3829 {
3830 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3831 int text_x = txt_x;
3832 int text_y = (216 + yofs) * mul;
3833 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3834 // int text_w = text_length(font, text.c_str());
3835 // int text_h = text_height(font);
3836 // static int grab_scale_tooltip_id = ttip_register_id();
3837 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3838 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3839
3840 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3841 break;
3842 }
3843
3844 case ftZGP:
3845 case ftQST:
3846 case ftZQT:
3847 case ftQSU:
3848 case ftTIL:
3849 case ftBIN:
3850 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3851 break;
3852 }
3853
3854 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3855 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3856
3857 if(bp==8)
3858 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3859 else
3860 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3861 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3862
3863 if(imagetype==ftBIN)
3864 {
3865 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3866 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3867 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3868 }
3869
3870 int fpath_y = (224+yofs)*mul;
3871 if(text_length(font,imagepath) <= max_fpath_wid)
3872 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3873 else
3874 {
3875 char buf[2052] = {0};
3876 strncpy(buf,imagepath,2048);
3877 int len = strlen(buf);
3878 char *ptr = buf;
3879 char *endptr = buf+len;
3880 char *it = endptr;
3881 int tmpy = fpath_y;
3882 int tmph = text_height(font)+1;
3883 while(true)
3884 {
3885 if(tmpy+tmph > (winh-2))
3886 break; //Out of space!
3887 char c = *it;
3888 bool end = !c;
3889 *it = 0;
3890 int newlen = text_length(font,ptr);
3891 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3892 {
3893 if(end) //No stored character, string ended
3894 {
3895 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 break;
3897 }
3898 char t[5];
3899 t[0] = c;
3900 for(int q = 1; q < 5; ++q)
3901 t[q] = it[q];
3902 strcpy(it,"...");
3903 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3904 for(int q = 0; q < 5; ++q)
3905 it[q] = t[q];
3906 tmpy += tmph;
3907 ptr = it;
3908 it = endptr;
3909 }
3910 else
3911 {
3912 *it = c;
3913 --it;
3914 }
3915 }
3916 }
3917 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3918 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3919 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3920 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3921
3922 //int32_t rectw = 16*mul;
3923 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3924 SCRFIX();
3925 font = oldfont;
3926 }
3927
3928 RGB_MAP rgb_table;
3929 COLOR_MAP imagepal_table;
3930
3931
3932 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3933 {
3934 //these are here to bypass compiler warnings about unused arguments
3935 x=x;
3936
3937 rgb->r = pal[y].r;
3938 rgb->g = pal[y].g;
3939 rgb->b = pal[y].b;
3940 }
3941
3942
3943 void load_imagebuf()
3944 {
3945 PACKFILE *f;
3946 //cache QRS
3947 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3948 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3949 // {
3950 // cached_rules[q] = quest_rules[q];
3951 // }
3952 bool compressed=false;
3953 bool encrypted=false;
3954 tiledata *hold=newtilebuf;
3955 zquestheader tempheader;
3956 memset(&tempheader, 0, sizeof(zquestheader));
3957
3958 if(imagebuf)
3959 {
3960 switch(imagetype)
3961 {
3962 case ftBMP:
3963 if (original_imagebuf_bitmap != imagebuf)
3964 destroy_bitmap((BITMAP*)imagebuf);
3965 destroy_bitmap(original_imagebuf_bitmap);
3966 break;
3967
3968 case ftZGP:
3969 case ftQST:
3970 case ftZQT:
3971 case ftQSU:
3972 case ftTIL:
3973 clear_tiles(grabtilebuf);
3974 break;
3975
3976 case ftBIN:
3977 free(imagebuf);
3978 break;
3979 }
3980
3981 imagebuf=NULL;
3982 original_imagebuf_bitmap=NULL;
3983 }
3984
3985 selx=sely=romofs=0;
3986 bp=4;
3987 imagetype=filetype(imagepath);
3988
3989 dword section_id;
3990 dword section_version;
3991 dword section_cversion;
3992
3993 switch(imagetype)
3994 {
3995 case ftBMP:
3996 packfile_password("");
3997 memset(imagepal, 0, sizeof(PALETTE));
3998 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
3999 imagesize = file_size_ex_password(imagepath,"");
4000 tilecount=0;
4001 create_rgb_table(&rgb_table, imagepal, NULL);
4002 rgb_map = &rgb_table;
4003 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4004
4005 if(!original_imagebuf_bitmap)
4006 {
4007 imagetype=0;
4008 }
4009 else
4010 {
4011 imagebuf = original_imagebuf_bitmap;
4012 imagebuf_bitmap_scale = 1;
4013 }
4014
4015 break;
4016
4017 case ftBIN:
4018 packfile_password("");
4019 imagesize = file_size_ex_password(imagepath, "");
4020 tilecount=0;
4021
4022 if(imagesize)
4023 {
4024 imagebuf = malloc(imagesize);
4025
4026 if(!readfile(imagepath,imagebuf,imagesize))
4027 {
4028 free(imagebuf);
4029 imagesize=0;
4030 imagetype=0;
4031 }
4032 }
4033
4034 break;
4035
4036 case ftTIL:
4037 packfile_password("");
4038 imagesize = file_size_ex_password(imagepath,"");
4039 f = pack_fopen_password(imagepath,F_READ,"");
4040
4041 if(!f)
4042 {
4043 goto error;
4044 }
4045
4046 if(!p_mgetl(&section_id,f))
4047 {
4048 goto error;
4049 }
4050
4051 if(section_id==ID_TILES)
4052 {
4053 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4054 {
4055 goto error;
4056 }
4057 }
4058
4059 error:
4060 pack_fclose(f);
4061 tilecount=count_tiles(grabtilebuf);
4062 break;
4063
4064 case ftZGP:
4065 packfile_password("");
4066 imagesize = file_size_ex_password(imagepath, "");
4067 f=pack_fopen_password(imagepath,F_READ,"");
4068
4069 if(!f)
4070 {
4071 goto error2;
4072 }
4073
4074 if(!p_mgetl(&section_id,f))
4075 {
4076 goto error2;
4077 }
4078
4079 if(section_id!=ID_GRAPHICSPACK)
4080 {
4081 goto error2;
4082 }
4083
4084 //section version info
4085 if(!p_igetw(&section_version,f))
4086 {
4087 goto error2;
4088 }
4089
4090 if(!p_igetw(&section_cversion,f))
4091 {
4092 goto error2;
4093 }
4094
4095 //tiles
4096 if(!p_mgetl(&section_id,f))
4097 {
4098 goto error2;
4099 }
4100
4101 if(section_id==ID_TILES)
4102 {
4103 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4104 {
4105 goto error2;
4106 }
4107 }
4108
4109 error2:
4110 pack_fclose(f);
4111 tilecount=count_tiles(grabtilebuf);
4112 break;
4113
4114 case ftQST:
4115 encrypted=true;
4116 case ftZQT:
4117 compressed=true;
4118 case ftQSU:
4119 packfile_password("");
4120 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4121 newtilebuf=grabtilebuf;
4122 byte skip_flags[4];
4123
4124 for(int32_t i=0; i<skip_max; ++i)
4125 {
4126 set_bit(skip_flags,i,1);
4127 }
4128
4129 set_bit(skip_flags,skip_tiles,0);
4130 set_bit(skip_flags,skip_header,0);
4131 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4132 if (ret)
4133 {
4134 imagetype=0;
4135 imagesize=0;
4136 clear_tiles(grabtilebuf);
4137 chop_path(imagepath);
4138 }
4139
4140 if (!ret && encrypted && compressed)
4141 {
4142 if(quest_access(imagepath, &tempheader) != 1)
4143 {
4144 imagetype=0;
4145 imagesize=0;
4146 clear_tiles(grabtilebuf);
4147 chop_path(imagepath);
4148 }
4149 }
4150
4151 //setPackfilePassword(NULL);
4152 newtilebuf=hold;
4153 tilecount=count_tiles(grabtilebuf);
4154 break;
4155 }
4156
4157 rgb_map = &zq_rgb_table;
4158 //restore cashed QRs / rules
4159
4160 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4161 // {
4162 // quest_rules[q] = cached_rules[q];
4163 // }
4164 }
4165
4166 static char bitstrbuf[32];
4167 bool leeching_from_tiles=false;
4168
4169 const char *bitlist(int32_t index, int32_t *list_size)
4170 {
4171 int32_t imported=2;
4172
4173 if(index>=0)
4174 {
4175 bound(index,0,leeching_from_tiles?2:1);
4176
4177 if(index==imported)
4178 {
4179 sprintf(bitstrbuf,"Imported");
4180 }
4181 else
4182 {
4183 sprintf(bitstrbuf,"%d",4<<index);
4184 }
4185
4186 return bitstrbuf;
4187 }
4188
4189 *list_size=leeching_from_tiles?3:2;
4190 return NULL;
4191 }
4192
4193 9 static ListData bit_list(bitlist, &font);
4194
4195 static DIALOG leech_dlg[] =
4196 {
4197 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4198 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4199 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4200 // 2
4201 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4202 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4203 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4204 // 5
4205 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4206 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4207 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4208 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4209 //9
4210 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4211 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4212
4213 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4214 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4215 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4216 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4218 //16
4219 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4220 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4221 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222
4223 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4224 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4225 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226
4227 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4228 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4229 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230
4231 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4232 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4233 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234
4235 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4236 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4237 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4238 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4239 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4240 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4241 };
4242
4243 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4244 {
4245 bool shift=true; // fix this!
4246 int32_t cst=0;
4247 int32_t currtile=start;
4248 int32_t height=0, width=0;
4249 byte *testtile = new byte[tilesize(tf32Bit)];
4250 byte imported_format=0;
4251 char updatestring[6];
4252 bool canadd;
4253 bool temp_canadd;
4254 bool duplicate;
4255 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4256 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4257 {
4258 0,0,0,0
4259 };
4260 BITMAP *status;
4261 status = create_bitmap_ex(8,240,140);
4262 clear_bitmap(status);
4263 sprintf(updatestring, "%d", LeechUpdate);
4264 leech_dlg[0].dp2=get_zc_font(font_lfont);
4265 leech_dlg[6].dp=updatestring;
4266
4267 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4268
4269 for(int32_t i=0; i<2; i++)
4270 {
4271 leech_dlg[i+7].flags=0;
4272 }
4273
4274 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4275
4276 for(int32_t i=0; i<12; i++)
4277 {
4278 leech_dlg[i+16].flags=0;
4279 }
4280
4281 for(int32_t i=0; i<4; i++)
4282 {
4283 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4284 }
4285
4286 leech_dlg[31].d1=0;
4287
4288 large_dialog(leech_dlg);
4289
4290 int32_t ret = do_zqdialog(leech_dlg,3);
4291
4292 if(ret==2)
4293 {
4294 delete[] testtile;
4295 return false;
4296 }
4297
4298 int32_t cdepth=leech_dlg[31].d1+1;
4299 int32_t newformat=0;
4300 auto lu = atoi(updatestring);
4301 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4302 if(LeechUpdate!=lu)
4303 {
4304 LeechUpdate=lu;
4305 zc_set_config("zquest","leech_update",LeechUpdate);
4306 }
4307 if(LeechUpdateTiles!=lut)
4308 {
4309 LeechUpdateTiles=lut;
4310 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4311 }
4312
4313 int32_t old_dupe[4];
4314 for(int32_t j=0; j<4; j++)
4315 {
4316 old_dupe[j] = DuplicateAction[j];
4317 for(int32_t i=0; i<3; i++)
4318 {
4319 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4320 {
4321 DuplicateAction[j]=i;
4322 }
4323 }
4324 }
4325 if(old_dupe[0] != DuplicateAction[0])
4326 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4327 if(old_dupe[1] != DuplicateAction[1])
4328 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4329 if(old_dupe[2] != DuplicateAction[2])
4330 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4331 if(old_dupe[3] != DuplicateAction[3])
4332 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4333
4334 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4335 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4336 {
4337 OnlyCheckNewTilesForDuplicates=ocntfd;
4338 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4339 }
4340
4341 leeching_from_tiles=false;
4342
4343 switch(imagetype)
4344 {
4345 case ftBIN:
4346 width=imagesize/128;
4347 height=1;
4348 break;
4349
4350 case ftZGP:
4351 case ftQST:
4352 case ftZQT:
4353 case ftQSU:
4354 case ftTIL:
4355 leeching_from_tiles=true;
4356 width=count_tiles(grabtilebuf);
4357 height=1;
4358 break;
4359
4360 case ftBMP:
4361 width=((((BITMAP*)imagebuf)->w)+15)/16;
4362 height=((((BITMAP*)imagebuf)->h)+15)/16;
4363 break;
4364 }
4365
4366 if(currtile+(width*height)>NEWMAXTILES)
4367 {
4368 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4369 {
4370 delete[] testtile;
4371 return false;
4372 }
4373 }
4374
4375 go_tiles();
4376 saved=false;
4377
4378 // usetiles=true;
4379 for(int32_t ty=0; ty<height; ty++) //for every row
4380 {
4381 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4382 {
4383 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4384 {
4385 FONT *oldfont = font;
4386 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4387 static bool created_tbar=false;
4388 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4389
4390 if(created_tbar)
4391 {
4392 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4393 }
4394 else
4395 {
4396 font = get_zc_font(font_lfont);
4397 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4398 font = oldfont;
4399 created_tbar=true;
4400 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4401 }
4402
4403 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4404 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4405 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4406 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4407 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4408 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4409 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4410 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4412 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4413 blit(status,screen,0, 0, 40, 20, 240, 140);
4414 SCRFIX();
4415 }
4416
4417 canadd=true;
4418
4419 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4420 {
4421 delete[] testtile;
4422 return true;
4423 }
4424
4425 switch(imagetype)
4426 {
4427 case ftBIN:
4428 break;
4429
4430 case ftZGP:
4431 case ftQST:
4432 case ftZQT:
4433 case ftQSU:
4434 case ftTIL:
4435 memset(testtile, 0, tilesize(tf32Bit));
4436 imported_format=grabtilebuf[tx].format;
4437
4438 switch(cdepth)
4439 {
4440 case 1: //4-bit
4441 newformat=tf4Bit;
4442
4443 switch(imported_format)
4444 {
4445 case tf4Bit:
4446 case tf8Bit:
4447 for(int32_t y=0; y<16; y++) //snag a tile
4448 {
4449 for(int32_t x=0; x<16; x+=2)
4450 {
4451 testtile[(y*8)+(x/2)]=
4452 (grabtilebuf[tx].data[y*16+x]&15)+
4453 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4454 }
4455 }
4456
4457 break;
4458 }
4459
4460 break;
4461
4462 case 2: //8-bit
4463 newformat=tf8Bit;
4464
4465 switch(imported_format)
4466 {
4467 case tf4Bit:
4468 unpack_tile(grabtilebuf, tx, 0, true);
4469 cst = cs&15;
4470 cst <<= CSET_SHFT;
4471
4472 for(int32_t i=0; i<256; i++)
4473 {
4474 if(!shift||unpackbuf[i]!=0)
4475 {
4476 unpackbuf[i]+=cst;
4477 }
4478 }
4479
4480 pack_tiledata(testtile, unpackbuf, tf8Bit);
4481 break;
4482
4483 case tf8Bit:
4484 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4485 break;
4486 }
4487
4488 break;
4489
4490 case 3: //original tile's bit depth
4491 newformat=imported_format;
4492 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4493 break;
4494 }
4495
4496 break;
4497
4498 case ftBMP:
4499 newformat=cdepth;
4500
4501 for(int32_t y=0; y<16; y++) //snag a tile
4502 {
4503 for(int32_t x=0; x<16; x+=2)
4504 {
4505 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4506 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4507 }
4508 }
4509
4510 break;
4511 }
4512
4513 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4514 {
4515 temp_canadd=true;
4516
4517 //check all tiles before this one
4518 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4519 {
4520 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4521 {
4522 if(DuplicateAction[flipping]>0)
4523 {
4524 if(keypressed())
4525 {
4526 delete[] testtile;
4527 return true;
4528 }
4529
4530 duplicate=(newformat==imported_format);
4531
4532 if(duplicate)
4533 {
4534 switch(flipping)
4535 {
4536 case 0: //normal
4537 if(dest[checktile].data!=NULL)
4538 {
4539 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4540 {
4541 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4542 {
4543 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4544 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4545 {
4546 duplicate=false;
4547 }
4548 }
4549 }
4550 }
4551
4552 break;
4553
4554 case 1: //horizontal
4555 if(dest[checktile].data!=NULL)
4556 {
4557 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4558 {
4559 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4560 {
4561 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4562 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4563 {
4564 duplicate=false;
4565 }
4566 }
4567 }
4568 }
4569
4570 break;
4571
4572 case 2: //vertical
4573 if(dest[checktile].data!=NULL)
4574 {
4575 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4576 {
4577 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4578 {
4579 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4580 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4581 {
4582 duplicate=false;
4583 }
4584 }
4585 }
4586 }
4587
4588 break;
4589
4590 case 3: //both
4591 if(dest[checktile].data!=NULL)
4592 {
4593 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4594 {
4595 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4596 {
4597 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4598 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4599 {
4600 duplicate=false;
4601 }
4602 }
4603 }
4604 }
4605
4606 break;
4607 }
4608 }
4609
4610 if(duplicate==true)
4611 {
4612 ++duplicates_found[flipping];
4613 ++total_duplicates_found;
4614
4615 if(DuplicateAction[flipping]>1)
4616 {
4617 ++total_duplicates_discarded;
4618 temp_canadd=false;
4619 }
4620 }
4621 }
4622
4623 canadd=canadd&&temp_canadd;
4624 }
4625 }
4626 }
4627
4628 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4629 dest[currtile].format=newformat;
4630
4631 if(dest[currtile].data!=NULL)
4632 {
4633 free(dest[currtile].data);
4634 }
4635
4636 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4637
4638 if(dest[currtile].data==NULL)
4639 {
4640 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4641 }
4642
4643 if(canadd==true)
4644 {
4645 /*
4646 for(int32_t y=0; y<16; y++)
4647 {
4648 for(int32_t x=0; x<8; x++)
4649 {
4650 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4651 }
4652 }
4653 */
4654 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4655 ++currtile;
4656 }
4657 }
4658 }
4659
4660 destroy_bitmap(status);
4661 delete[] testtile;
4662 return true;
4663 }
4664
4665 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4666 {
4667 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4668 byte format=defFormat;
4669 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4670
4671 switch(imagetype)
4672 {
4673 case ftZGP:
4674 case ftQST:
4675 case ftZQT:
4676 case ftQSU:
4677 case ftTIL:
4678 case ftBIN:
4679 case ftBMP:
4680 for(int32_t ty=0; ty<height; ty++)
4681 {
4682 for(int32_t tx=0; tx<width; tx++)
4683 {
4684 format=defFormat;
4685 switch(imagetype)
4686 {
4687 case ftZGP:
4688 case ftQST:
4689 case ftZQT:
4690 case ftQSU:
4691 case ftTIL:
4692 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4693 break;
4694 }
4695
4696 bool ever_did_unmasked = false;
4697
4698 for(int32_t y=0; y<16; y++)
4699 {
4700 for(int32_t x=0; x<16; x+=2)
4701 {
4702 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4703 if (masked)
4704 {
4705 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4706 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4707 }
4708 else
4709 {
4710 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4711 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4712 ever_did_unmasked = true;
4713 }
4714 if (format == tf4Bit)
4715 {
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4717 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4718 }
4719 }
4720 }
4721
4722 if (ever_did_unmasked)
4723 newformat[(ty*TILES_PER_ROW)+tx] = format;
4724 }
4725 }
4726
4727 break;
4728
4729 default:
4730 for(int32_t i=0; i<200; i++)
4731 {
4732 for(int32_t j=0; j<256; j++)
4733 {
4734 dest[i][j]=0;
4735 }
4736
4737 newformat[i] = tf4Bit;
4738 }
4739
4740 break;
4741 }
4742 }
4743
4744 static void scale_imagebuf_bitmap()
4745 {
4746 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4747
4748 float scale = IMAGEBUF_SCALE;
4749 int nw = original_imagebuf_bitmap->w * scale;
4750 int nh = original_imagebuf_bitmap->h * scale;
4751 if (nw <= 0 || nh <= 0)
4752 return;
4753
4754 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4755 if (!scaled_bmp)
4756 return;
4757
4758 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4759 if (imagebuf != original_imagebuf_bitmap)
4760 destroy_bitmap((BITMAP*)imagebuf);
4761 imagebuf = scaled_bmp;
4762 }
4763
4764 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4765 void grab_tile(int32_t tile,int32_t &cs)
4766 {
4767 zq_allow_tile_draw_cache = true;
4768
4769 int window_w = 640+6+6, window_h = 480+25+6;
4770 int window_x=(zq_screen_w-window_w)/2;
4771 int window_y=(zq_screen_h-window_h)/2;
4772 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4773 int window_xofs = 0;
4774 int screen_xofs=6;
4775 int screen_yofs=25;
4776 int panel_yofs=0;
4777 int bwidth = 61*1.5;
4778 int bheight = 20*1.5;
4779 int button_x = 255*2;
4780 int grab_ok_button_y = 168*2 + 32;
4781 int leech_button_x = 117*2;
4782 int leech_button_y = 166*2 + 32;
4783 int grab_cancel_button_y = 192*2 + 32;
4784 int file_button_y = 216*2 + 32;
4785 int rec_button_x = 117*2;
4786 int rec_button_y = 192*2 + 32;
4787
4788 int screen_y1 = 24;
4789 int screen_y2 = screen_y1+320-1;
4790
4791 int crect_x = 184+190;
4792 int crect_y = 168*2 + 32;
4793 int crect_w = 8*2;
4794 int crect_h = 8*2;
4795
4796 int xrect_x = 640 + 12 - 21;
4797 int xrect_y = 5;
4798
4799 byte newtile[200][256];
4800 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4801 clear_bitmap(screen3);
4802 byte newformat[200];
4803
4804 memset(newtile, 0, 200*256);
4805 memset(newformat, 0, 200);
4806
4807 static EXT_LIST list[] =
4808 {
4809 { (char *)"All Files (*.*)", NULL },
4810 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4811 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4812 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4813 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4814 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4815 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4816 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4817 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4818 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4819 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4820 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4821 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4822 { NULL, NULL }
4823 };
4824
4825
4826 memset(cset_reduce_table, 0, 256);
4827 memset(col_diff,0,3*128);
4828 bool bdown=false;
4829 int done=0;
4830 int pal=0;
4831 int f=0;
4832 int black=vc(0),white=vc(15);
4833 int selwidth=1, selheight=1;
4834 int selx2=0, sely2=0;
4835 bool xreversed=false, yreversed=false;
4836 bool doleech=false, dofile=false, dopal=false;
4837
4838 int jwin_pal2[jcMAX];
4839 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4840
4841
4842 if(imagebuf==NULL)
4843 load_imagebuf();
4844
4845 calc_cset_reduce_table(imagepal, cs);
4846 calc_cset_reduce_table_8bit(imagepal);
4847 draw_grab_window();
4848 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4849 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4850
4851 while(gui_mouse_b())
4852 {
4853 /* do nothing */
4854 rest(1);
4855 }
4856
4857 do
4858 {
4859 HANDLE_CLOSE_ZQDLG();
4860 if(exiting_program) break;
4861 rest(4);
4862 bool redraw=false;
4863
4864 if(keypressed())
4865 {
4866 redraw=true;
4867
4868 switch(readkey()>>8)
4869 {
4870 case KEY_F:
4871 dofile=true;
4872 break;
4873
4874 case KEY_L:
4875 doleech=true;
4876 break;
4877
4878 case KEY_P:
4879 if(imagetype==ftBMP)
4880 {
4881 dopal=true;
4882 recolor=rcNone;
4883 calc_cset_reduce_table(imagepal, cs);
4884 }
4885
4886 break;
4887
4888 case KEY_ESC:
4889 done=1;
4890 break;
4891
4892 case KEY_ENTER_PAD:
4893 case KEY_ENTER:
4894 done=2;
4895 break;
4896
4897 case KEY_DOWN:
4898 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4899 else ++imagey;
4900
4901 break;
4902
4903 case KEY_UP:
4904 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4905 else --imagey;
4906
4907 break;
4908
4909 case KEY_RIGHT:
4910 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4911 else ++imagex;
4912
4913 break;
4914
4915 case KEY_LEFT:
4916 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4917 else --imagex;
4918
4919 break;
4920
4921 case KEY_PGDN:
4922 imagey+=10;
4923 break;
4924
4925 case KEY_PGUP:
4926 imagey-=10;
4927 break;
4928
4929 case KEY_HOME:
4930 imagex=imagey=0;
4931 break;
4932
4933 case KEY_EQUALS:
4934 case KEY_PLUS_PAD:
4935 cs = (cs<13) ? cs+1:0;
4936 if(recolor==rc4Bit)
4937 calc_cset_reduce_table(imagepal, cs);
4938 break;
4939
4940 case KEY_MINUS:
4941 case KEY_MINUS_PAD:
4942 cs = (cs>0) ? cs-1:13;
4943 if(recolor==rc4Bit)
4944 calc_cset_reduce_table(imagepal, cs);
4945 break;
4946
4947 case KEY_S:
4948 if(grabmode==1) grabmode=8;
4949 else if(grabmode==8) grabmode=16;
4950 else grabmode=1;
4951
4952 break;
4953
4954 case KEY_COMMA:
4955 if (imagetype == ftBMP)
4956 {
4957 imagebuf_bitmap_scale--;
4958 if (imagebuf_bitmap_scale == 0)
4959 imagebuf_bitmap_scale = -2;
4960 scale_imagebuf_bitmap();
4961 }
4962 break;
4963 case KEY_STOP:
4964 if (imagetype == ftBMP)
4965 {
4966 imagebuf_bitmap_scale++;
4967 if (imagebuf_bitmap_scale == -1)
4968 imagebuf_bitmap_scale = 1;
4969 scale_imagebuf_bitmap();
4970 }
4971 break;
4972
4973 case KEY_1:
4974 if(recolor==rc8Bit)
4975 recolor=rcNone;
4976 //imagex=(imagex*bp)>>3;
4977 bp=1;
4978 //imagex<<=3;
4979 nesmode=false;
4980 break;
4981
4982 case KEY_2:
4983 if(recolor==rc8Bit)
4984 recolor=rcNone;
4985 //imagex=(imagex*bp)>>3;
4986 bp=2;
4987 //imagex<<=2;
4988 nesmode=false;
4989 break;
4990
4991 case KEY_N:
4992 if(recolor==rc8Bit)
4993 recolor=rcNone;
4994 //imagex=(imagex*bp)>>3;
4995 bp=2;
4996 //imagex<<=2;
4997 nesmode=true;
4998 break;
4999
5000 case KEY_4:
5001 if(recolor==rc8Bit)
5002 recolor=rcNone;
5003 //imagex=(imagex*bp)>>3;
5004 bp=4;
5005 //imagex<<=1;
5006 nesmode=false;
5007 break;
5008
5009 case KEY_8:
5010 //imagex=(imagex*bp)>>3;
5011 bp=8;
5012 break;
5013
5014 case KEY_B:
5015 if(bp==2&&!nesmode)
5016 {
5017 nesmode=true;
5018 }
5019 else
5020 {
5021 nesmode=false;
5022 bp<<=1;
5023
5024 if(bp==16)
5025 {
5026 bp=1;
5027 //imagex<<=3;
5028 }
5029 else
5030 {
5031 //imagex>>=1;
5032 }
5033 }
5034
5035 break;
5036
5037 case KEY_M:
5038 romtilemode=(romtilemode+1)%4;
5039 break;
5040
5041 case KEY_Z:
5042 if(romofs>0) --romofs;
5043
5044 break;
5045
5046 case KEY_X:
5047 ++romofs;
5048 break;
5049
5050 case KEY_R:
5051 if(pal)
5052 {
5053 dopal=true;
5054 }
5055
5056 if(recolor!=rcNone)
5057 recolor=rcNone;
5058 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5059 {
5060 bp=8;
5061 recolor=rc8Bit;
5062 calc_cset_reduce_table_8bit(imagepal);
5063 }
5064 else
5065 {
5066 if(bp==8)
5067 bp=4;
5068 recolor=rc4Bit;
5069 calc_cset_reduce_table(imagepal, cs);
5070 }
5071 break;
5072
5073 default:
5074 redraw=false;
5075 }
5076
5077 clear_keybuf();
5078
5079 if(imagex<0) imagex=0;
5080
5081 if(imagey<0) imagey=0;
5082
5083 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5084 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5085 }
5086
5087 //boogie!
5088 if(gui_mouse_b()==1 && !bdown)
5089 {
5090 int x=gui_mouse_x();
5091 int y=gui_mouse_y();
5092 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5093 if(do_x_button(screen, xrect_x, xrect_y))
5094 done=1;
5095
5096 if(!bdown)
5097 {
5098 bool regrab=false;
5099 bdown=true;
5100 FONT* oldfont = font;
5101 font = get_zc_font(font_lfont_l);
5102
5103 if(y>=screen_y1 && y<=screen_y2)
5104 {
5105 do
5106 {
5107 HANDLE_CLOSE_ZQDLG();
5108 if(exiting_program) break;
5109 int x = (gui_mouse_x()-screen_xofs) / 2;
5110 int y = (gui_mouse_y()-screen_yofs) / 2;
5111
5112 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5113
5114 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5115 {
5116 selx=vbound((x/grabmode)*grabmode,0,304);
5117 sely=vbound((y/grabmode)*grabmode,0,144);
5118 selx2=selx;
5119 sely2=sely;
5120 selwidth=1;
5121 selheight=1;
5122 xreversed=false;
5123 yreversed=false;
5124 }
5125 else
5126 {
5127 if(xreversed)
5128 {
5129 zc_swap(selx, selx2);
5130 xreversed=false;
5131 }
5132
5133 if(yreversed)
5134 {
5135 zc_swap(sely, sely2);
5136 yreversed=false;
5137 }
5138
5139 selx2=vbound((x/grabmode)*grabmode,0,304);
5140 sely2=vbound((y/grabmode)*grabmode,0,144);
5141 selwidth=1+(abs(selx2-selx))/16;
5142 selheight=1+(abs(sely2-sely))/16;
5143
5144 if(selx2<selx)
5145 {
5146 zc_swap(selx, selx2);
5147 xreversed=true;
5148 }
5149
5150 if(sely2<sely)
5151 {
5152 zc_swap(sely, sely2);
5153 yreversed=true;
5154 }
5155 }
5156
5157 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5158 bool redraw = changed || !(f%8);
5159
5160 if(redraw)
5161 {
5162 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5163 if(changed)
5164 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5165 if(f&8)
5166 {
5167 static const int w = 32;
5168 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5169 }
5170 }
5171 else custom_vsync();
5172
5173 ++f;
5174 }
5175 while(gui_mouse_b());
5176 }
5177 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5178 {
5179 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5180 done=2;
5181 }
5182 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5183 {
5184 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5185 {
5186 doleech=true;
5187 }
5188 }
5189 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5190 {
5191 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5192 done=1;
5193 }
5194 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5195 {
5196 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5197 {
5198 dofile=true;
5199 }
5200 }
5201 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5202 {
5203 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5204 {
5205 if(pal)
5206 {
5207 dopal = true;
5208 }
5209
5210 if(recolor!=rcNone)
5211 recolor=rcNone;
5212 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5213 {
5214 bp=8;
5215 recolor=rc8Bit;
5216 calc_cset_reduce_table_8bit(imagepal);
5217 }
5218 else
5219 {
5220 if(bp==8)
5221 bp=4;
5222 recolor=rc4Bit;
5223 calc_cset_reduce_table(imagepal, cs);
5224 }
5225 redraw=true;
5226 }
5227 }
5228 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5229 {
5230 regrab=true;
5231 grabmask^=1;
5232 }
5233 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5234 {
5235 regrab=true;
5236 grabmask^=2;
5237 }
5238 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5239 {
5240 regrab=true;
5241 grabmask^=4;
5242 }
5243 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5244 {
5245 regrab=true;
5246 grabmask^=8;
5247 }
5248
5249 if(regrab)
5250 {
5251 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5252 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5253 redraw=true;
5254 }
5255
5256 font = oldfont;
5257 }
5258 }
5259
5260 if(gui_mouse_b()==0)
5261 bdown=false;
5262
5263 if(dofile)
5264 {
5265 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5266 {
5267 zc_set_palette(RAMpal);
5268 pal=0;
5269 white=vc(15);
5270 black=vc(0);
5271 strcpy(imagepath,temppath);
5272 load_imagebuf();
5273 imagex=imagey=0;
5274 calc_cset_reduce_table(imagepal, cs);
5275 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5276 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5277 }
5278
5279 while(key[KEY_ESC])
5280 {
5281 poll_keyboard();
5282 /* do nothing */
5283 rest(1);
5284 }
5285
5286 clear_keybuf();
5287 dofile=false;
5288 redraw=true;
5289 }
5290
5291 if(doleech)
5292 {
5293 if(leech_tiles(newtilebuf,tile,cs))
5294 {
5295 done=1;
5296 }
5297 else
5298 {
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 redraw=true;
5308 }
5309
5310 doleech=false;
5311 }
5312
5313 if(dopal)
5314 {
5315 pal^=1;
5316
5317 if(pal)
5318 {
5319 get_bw(imagepal,black,white);
5320
5321 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5322 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5323 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5324 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5325 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5326 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5327 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5328 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5329 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5330 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5331 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5332 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5333 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5334 gui_bg_color=jwin_pal[jcBOX];
5335 gui_fg_color=jwin_pal[jcBOXFG];
5336 jwin_set_colors(jwin_pal);
5337 }
5338 else
5339 {
5340 white=vc(15);
5341 black=vc(0);
5342
5343 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5344 gui_bg_color=jwin_pal[jcBOX];
5345 gui_fg_color=jwin_pal[jcBOXFG];
5346 jwin_set_colors(jwin_pal);
5347 }
5348
5349 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5350
5351 dopal=false;
5352 redraw=true;
5353 }
5354
5355 if(redraw)
5356 {
5357 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5358 }
5359 else
5360 {
5361 custom_vsync();
5362 }
5363
5364 if((f%8)==0)
5365 {
5366 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5367
5368 int selxl = selx* 2;
5369 int selyl = sely* 2;
5370 int w = 32;
5371
5372 if(f&8)
5373 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5374
5375 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5376 }
5377
5378 // SCRFIX();
5379 ++f;
5380
5381 }
5382 while(!done);
5383
5384 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5385 gui_bg_color=jwin_pal[jcBOX];
5386 gui_fg_color=jwin_pal[jcBOXFG];
5387 jwin_set_colors(jwin_pal);
5388
5389
5390 if(done==2)
5391 {
5392 go_tiles();
5393 saved=false;
5394
5395 // usetiles=true;
5396 for(int y=0; y<selheight; y++)
5397 {
5398 for(int x=0; x<selwidth; x++)
5399 {
5400 int temptile=tile+((TILES_PER_ROW*y)+x);
5401 int format=(bp==8) ? tf8Bit : tf4Bit;
5402
5403 if(newtilebuf[temptile].data!=NULL)
5404 free(newtilebuf[temptile].data);
5405
5406 newtilebuf[temptile].format=format;
5407 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5408
5409 if(newtilebuf[temptile].data==NULL)
5410 {
5411 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5412 break;
5413 }
5414
5415 for(int i=0; i<256; i++)
5416 {
5417 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5418 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5419 }
5420
5421 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5422 }
5423 }
5424 }
5425
5426 destroy_bitmap(screen3);
5427
5428 if(pal)
5429 zc_set_palette(RAMpal);
5430
5431 recolor=rcNone;
5432 calc_cset_reduce_table(imagepal, cs);
5433 register_blank_tiles();
5434 popup_zqdialog_end();
5435
5436 zq_allow_tile_draw_cache = false;
5437 }
5438
5439 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5440 bool tile_is_used(int32_t tile)
5441 {
5442 return used_tile_table[tile];
5443 }
5444 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5445 {
5446 draw_tiles(screen2, first, cs, f, true);
5447 }
5448 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5449 {
5450 clear_bitmap(dest);
5451 BITMAP *buf = create_bitmap_ex(8,16,16);
5452
5453 int32_t w = 16;
5454 int32_t h = 16;
5455
5456 if(large)
5457 {
5458 w *=2;
5459 h *=2;
5460 }
5461
5462 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5463 {
5464 int32_t x = (i%TILES_PER_ROW)<<4;
5465 int32_t y = (i/TILES_PER_ROW)<<4;
5466 int32_t l = 16;
5467
5468 if(large)
5469 {
5470 x*=2;
5471 y*=2;
5472 l*=2;
5473 }
5474
5475 l-=2;
5476
5477 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5478 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5479 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5480 {
5481 if(!true_empty) //Use pure color 0; no effects
5482 {
5483 if (InvalidBG == 2)
5484 {
5485 draw_checkerboard(dest, x, y, w);
5486 }
5487 else if(InvalidBG == 1)
5488 {
5489 for(int32_t dy=0; dy<=l+1; dy++)
5490 {
5491 for(int32_t dx=0; dx<=l+1; dx++)
5492 {
5493 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5494 }
5495 }
5496 }
5497 else
5498 {
5499 for(int32_t dy=0; dy<=l+1; dy++)
5500 {
5501 for(int32_t dx=0; dx<=l+1; dx++)
5502 {
5503 dest->line[dy+(y)][dx+(x)]=vc(0);
5504 }
5505 }
5506 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5507 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5508 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5509 }
5510 }
5511 }
5512 else
5513 {
5514 puttile16(buf,first+i,0,0,cs,0);
5515 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5516 }
5517
5518 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5519 {
5520 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5521 }
5522 }
5523
5524 destroy_bitmap(buf);
5525 }
5526
5527 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5528 {
5529 int32_t yofs=3;
5530 BITMAP *buf = create_bitmap_ex(8,16,16);
5531 int32_t mul = 2;
5532 FONT *tfont = get_zc_font(font_pfont);
5533
5534 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5535 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5536 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5537 tfont = get_zc_font(font_lfont_l);
5538
5539 // Copied tile and numbers
5540 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5541 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5542 if(copy>=0)
5543 {
5544 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5545 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5546
5547 if(copycnt>1)
5548 {
5549 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5550 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5551 }
5552 else
5553 {
5554 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5555 }
5556 }
5557 else // No tiles copied
5558 {
5559 if (InvalidBG == 2)
5560 {
5561 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5562 }
5563 else if(InvalidBG == 1)
5564 {
5565 for(int32_t dy=0; dy<16*mul; dy++)
5566 {
5567 for(int32_t dx=0; dx<16*mul; dx++)
5568 {
5569 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5570 }
5571 }
5572 }
5573 else
5574 {
5575 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5576 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5577 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5578 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5579 }
5580 }
5581
5582
5583 // Current tile
5584 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5585 puttile16(buf,tile,0,0,cs,0);
5586 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5587
5588 // Current selection mode
5589 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5590 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5591
5592 if(tile>tile2)
5593 {
5594 zc_swap(tile,tile2);
5595 }
5596
5597 char tbuf[8];
5598 tbuf[0]=0;
5599
5600 if(tile2!=tile)
5601 {
5602 sprintf(tbuf,"-%d",tile2);
5603 }
5604
5605 // Current tile and CSet text
5606 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5607 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5608 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5609
5610 FONT *tf = font;
5611 font = tfont;
5612
5613 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5614 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5615 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5617 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5618
5619 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5620 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5621 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5622 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5623
5624 font = tf;
5625
5626 int32_t w = 640;
5627 int32_t h = 480;
5628 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5629 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5630 int32_t screen_xofs=window_xofs+6;
5631 int32_t screen_yofs=window_yofs+25;
5632
5633 custom_vsync();
5634 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5635 SCRFIX();
5636 destroy_bitmap(buf);
5637 }
5638
5639 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5640 {
5641 int32_t yofs=3;
5642 BITMAP *buf = create_bitmap_ex(8,16,16);
5643 int32_t mul = 2;
5644 FONT *tfont = get_zc_font(font_pfont);
5645
5646 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5647 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5648 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5649 tfont = get_zc_font(font_lfont_l);
5650
5651 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5652
5653 if(copy>=0)
5654 {
5655 puttile16(buf,copy,0,0,cs,flip);
5656 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5657 }
5658 else
5659 {
5660 if (InvalidBG == 2)
5661 {
5662 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5663 }
5664 else if(InvalidBG == 1)
5665 {
5666 for(int32_t dy=0; dy<16*mul; dy++)
5667 {
5668 for(int32_t dx=0; dx<16*mul; dx++)
5669 {
5670 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5671 }
5672 }
5673 }
5674 else
5675 {
5676 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5677 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5678 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5679 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5680 }
5681 }
5682
5683 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5684 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5685 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5686
5687 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5688 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5689
5690 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5691 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5692
5693 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5694 {
5695 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5696 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5697 }
5698
5699 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5700 puttile16(buf,tile,0,0, cs,
5701 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5702 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5703
5704 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5705 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5706 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5707 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5708
5709 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5710 {
5711 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5712 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5713 }
5714
5715 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5716 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5717 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5718 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5719
5720
5721 int32_t w = 640;
5722 int32_t h = 480;
5723 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5724 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5725 int32_t screen_xofs=window_xofs+6;
5726 int32_t screen_yofs=window_yofs+25;
5727
5728 custom_vsync();
5729 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5730 SCRFIX();
5731 destroy_bitmap(buf);
5732 }
5733 /*
5734 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5735 {
5736 buf[t].format=format;
5737 if (buf[t].data!=NULL)
5738 {
5739 free(buf[t].data);
5740 }
5741 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5742 if (buf[t].data==NULL)
5743 {
5744 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5745 }
5746 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5747 {
5748 buf[t].data[i]=0;
5749 }
5750 }
5751 */
5752
5753 int32_t hide_used()
5754 {
5755 show_only_unused_tiles ^= 1;
5756 return D_O_K;
5757 }
5758 int32_t hide_unused()
5759 {
5760 show_only_unused_tiles ^= 2;
5761 return D_O_K;
5762 }
5763 int32_t hide_blank()
5764 {
5765 show_only_unused_tiles ^= 4;
5766 return D_O_K;
5767 }
5768 int32_t hide_8bit_marker()
5769 {
5770 show_only_unused_tiles ^= 8;
5771 return D_O_K;
5772 }
5773
5774 enum
5775 {
5776 MENUID_SELTILE_VIEW_HIDE_USED,
5777 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5778 MENUID_SELTILE_VIEW_HIDE_BLANK,
5779 MENUID_SELTILE_VIEW_HIDE_8BIT,
5780 };
5781
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5782 45 {
5783
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5784
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5785
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5786
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5787 };
5788
5789 9 static std::function<void(int)> select_tile_color_depth_cb;
5790
5791 static void set_tile_color_depth_4()
5792 {
5793 select_tile_color_depth_cb(tf4Bit);
5794 }
5795 static void set_tile_color_depth_8()
5796 {
5797 select_tile_color_depth_cb(tf8Bit);
5798 }
5799 enum
5800 {
5801 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5802 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5803 };
5804
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5805 27 {
5806
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5807
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5808 };
5809
5810 //returns the row the tile is in on its page
5811 int32_t tile_page_row(int32_t tile)
5812 {
5813 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5814 }
5815
5816 enum {ti_none, ti_encompass, ti_broken};
5817
5818 //striped check and striped selection
5819 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5820 {
5821 int32_t cmb_first = cmb.o_tile;
5822 int32_t cmb_last = cmb.o_tile;
5823 do
5824 {
5825 cmb_last = cmb.tile;
5826 animate(cmb, true);
5827 }
5828 while(cmb.tile != cmb.o_tile);
5829 reset_combo_animation(cmb);
5830 cmb_first += offset;
5831 cmb_last += offset;
5832
5833 if(cmb_first > selection_last || cmb_last < selection_first)
5834 return ti_none;
5835 if(cmb_first >= selection_first && cmb_last <= selection_last)
5836 return ti_encompass;
5837
5838 do
5839 {
5840 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5841 {
5842 reset_combo_animation(cmb);
5843 return ti_broken; //contained, but non-encompassing.
5844 }
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 return ti_none;
5850 }
5851 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5852 {
5853 // if selection is before or after check...
5854 if((check_first>selection_last)||(selection_first>check_last))
5855 {
5856 return ti_none;
5857 }
5858
5859 // if selection envelopes check
5860 if((selection_first<=check_first)&&(selection_last>=check_last))
5861 {
5862 return ti_encompass; //encompass
5863 }
5864
5865 //everything else is a break
5866 return ti_broken; //intersect
5867 }
5868
5869
5870
5871 //rectangular check and striped selection
5872 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5873 {
5874 int32_t ret1=-1, ret2=-1;
5875
5876 for(int32_t i=0; i<check_height; ++i)
5877 {
5878 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5879 int32_t check_last=check_first+check_width-1;
5880 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5881
5882 if(ret2==ti_broken)
5883 {
5884 return ti_broken;
5885 }
5886
5887 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5888 }
5889
5890 if(ret1==ti_encompass)
5891 {
5892 if((TILEROW(selection_first)<=check_top) &&
5893 (TILEROW(selection_last)>=(check_top+check_height-1)))
5894 {
5895 return ti_encompass;
5896 }
5897 else
5898 {
5899 return ti_broken;
5900 }
5901 }
5902
5903 return ti_none;
5904 }
5905
5906
5907 //striped check and rectangular selection
5908 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5909 {
5910 if(selection_width < TILES_PER_ROW)
5911 {
5912 int32_t cmb_first = cmb.o_tile;
5913 int32_t cmb_last = cmb.o_tile;
5914 do
5915 {
5916 cmb_last = cmb.tile;
5917 animate(cmb, true);
5918 }
5919 while(cmb.tile != cmb.o_tile);
5920 reset_combo_animation(cmb);
5921 cmb_first += offset;
5922 cmb_last += offset;
5923
5924 if((TILEROW(cmb_first)>=selection_top) &&
5925 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5926 (TILECOL(cmb_first)>=selection_left) &&
5927 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5928 {
5929 return ti_encompass;
5930 }
5931 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5932 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5933 {
5934 return ti_none;
5935 }
5936
5937 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5938 {
5939 int32_t firstcol = TILECOL(cmb_first);
5940 int32_t lastcol = TILECOL(cmb_last);
5941
5942 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5943 return ti_none;
5944 else //handle skip x
5945 {
5946 do
5947 {
5948 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5949 {
5950 reset_combo_animation(cmb);
5951 return ti_broken;
5952 }
5953 animate(cmb, true);
5954 }
5955 while(cmb.tile != cmb.o_tile);
5956 reset_combo_animation(cmb);
5957 return ti_none;
5958 }
5959 }
5960 else //multi-row combo...
5961 {
5962 int32_t row = TILEROW(cmb_first);
5963
5964 do
5965 {
5966 if(row < selection_top || row > selection_top+selection_height-1)
5967 {
5968 //This row isn't in the selection; skip to next row
5969 do
5970 {
5971 animate(cmb,true);
5972 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5973 }
5974 while(TILEROW(cmb.tile) == row);
5975 row = TILEROW(cmb.tile);
5976 continue;
5977 }
5978
5979 //This row IS in the selection; check each tile.
5980 do
5981 {
5982 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5983 {
5984 reset_combo_animation(cmb);
5985 return ti_broken;
5986 }
5987 animate(cmb, true);
5988 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5989 }
5990 while(TILEROW(cmb.tile) == row);
5991 row = TILEROW(cmb.tile);
5992 }
5993 while(cmb.tile != cmb.o_tile);
5994
5995 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5996 }
5997 }
5998
5999 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6000 }
6001 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6002 {
6003 if(selection_width < TILES_PER_ROW)
6004 {
6005 if((check_last-check_first+1<=selection_width) &&
6006 (TILEROW(check_first)>=selection_top) &&
6007 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6008 (TILECOL(check_first)>=selection_left) &&
6009 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6010 {
6011 return ti_encompass;
6012 }
6013 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6014 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6015 {
6016 return ti_none;
6017 }
6018
6019 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6020
6021 //one last base case: the strip we're interested in only lies along one row
6022 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6023 {
6024 int32_t cfcol = check_first%TILES_PER_ROW;
6025 int32_t clcol = check_last%TILES_PER_ROW;
6026
6027 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6028 return ti_none;
6029 else
6030 return ti_broken;
6031 }
6032 else
6033 {
6034 //recursively cut the strip into substrips which lie entirely on one row
6035 int32_t currow = check_first/TILES_PER_ROW;
6036 int32_t endrow = check_last/TILES_PER_ROW;
6037 int32_t accum = 0;
6038 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6039
6040 for(++currow; currow<endrow; currow++)
6041 {
6042 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6043 }
6044
6045 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6046
6047 if(accum > 0)
6048 return ti_broken;
6049
6050 return ti_none;
6051 }
6052 }
6053
6054 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6055 }
6056
6057 //rectangular check and rectangular selection
6058 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6059 {
6060 if((check_left>=selection_left) &&
6061 (check_left+check_width<=selection_left+selection_width) &&
6062 (check_top>=selection_top) &&
6063 (check_top+check_height<=selection_top+selection_height))
6064 {
6065 return ti_encompass;
6066 }
6067 else
6068 {
6069 for(int32_t i=check_top; i<check_top+check_height; ++i)
6070 {
6071 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6072 {
6073 return ti_broken;
6074 }
6075 }
6076 }
6077
6078 return ti_none;
6079 }
6080
6081
6082
6083
6084 static DIALOG move_textbox_list_dlg[] =
6085 {
6086 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6087 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6088 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6089 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6090 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6091 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6092 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6093 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6094 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6095 };
6096
6097 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6098 {
6099 char buf1[512] = {0};
6100 char buf2[512] = {0};
6101 large_dialog(move_textbox_list_dlg);
6102 DIALOG& tbox = move_textbox_list_dlg[3];
6103 {
6104 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6105 int indx = 0, word_indx = 0;
6106 for(char c : msg)
6107 {
6108 if(c == ' ' || c == '\n')
6109 word_indx = indx;
6110 buf1[indx++] = c;
6111 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6112 {
6113 buf1[word_indx] = 0;
6114 strcpy(buf2, msg.c_str()+word_indx+1);
6115 break;
6116 }
6117 }
6118 }
6119
6120 move_textbox_list_dlg[0].dp = (void*)title;
6121 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6122 move_textbox_list_dlg[1].dp = buf1;
6123 move_textbox_list_dlg[2].dp = buf2;
6124 tbox.dp = textbox;
6125 tbox.d2 = 0;
6126 auto tby = tbox.y;
6127 auto tbh = tbox.h;
6128 if(!buf2[0])
6129 {
6130 auto diff = move_textbox_list_dlg[2].h;
6131 tbox.y -= diff;
6132 tbox.h += diff;
6133 }
6134
6135 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6136 position_mouse_z(0);
6137 tbox.y = tby;
6138 tbox.h = tbh;
6139
6140 return ret == 4;
6141 }
6142
6143 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6144 {
6145 return a==0?b:a==1?c:d;
6146 }
6147
6148 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6149 {
6150 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6151 int i = ti_none;
6152 auto t = ref->getTile() + ref->offset();
6153
6154 if(combo_ref)
6155 {
6156 if(proc.rect)
6157 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6158 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6159 }
6160 else if(proc.rect)
6161 {
6162 if(ref->h > 1)
6163 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6164 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6165 }
6166 else
6167 {
6168 if(ref->h > 1)
6169 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6170 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6171 }
6172
6173 bool in = i != ti_none, out = i != ti_encompass;
6174 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6175 {
6176 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6177 if(proc.rect)
6178 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6179 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6180 if(i != ti_none)
6181 in = true;
6182 if(i != ti_encompass)
6183 out = true;
6184 }
6185 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6186
6187 if(i != ti_none && ref->getTile() != 0)
6188 {
6189 if(mode == Mode::CHECK_ALL)
6190 {
6191 move_refs.emplace_back(std::move(ref));
6192 return true;
6193 }
6194 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6195 {
6196 if(warning_flood || warning_list.tellp() >= 65000)
6197 {
6198 if(!warning_flood)
6199 warning_list << "...\n...\n...\nmany others";
6200 warning_flood = true;
6201 }
6202 else
6203 warning_list << ref->name << '\n';
6204 }
6205 else if(i==ti_encompass)
6206 {
6207 move_refs.emplace_back(std::move(ref));
6208 return true;
6209 }
6210 }
6211 return false;
6212 }
6213
6214 bool TileMoveList::check_prot()
6215 {
6216 if(!TileProtection)
6217 return true;
6218 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6219
6220 warning_flood = false;
6221 warning_list.clear();
6222
6223 return ret;
6224 }
6225
6226 void TileMoveList::add_diff(int diff)
6227 {
6228 for(auto& ref : move_refs)
6229 ref->addTile(diff);
6230 }
6231
6232 //from 'combo.h'
6233 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6234 {
6235 int i = ti_none;
6236 auto c = ref->getCombo();
6237
6238 if(ref->no_move)
6239 processed_combos[c] = true;
6240 else processed_combos[c]; //inserts element if does not exist
6241 i = move_intersection_ss(c, c, proc._first, proc._last);
6242
6243 if(i != ti_none && ref->getCombo() != 0)
6244 {
6245 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6246 {
6247 if(ComboProtection)
6248 {
6249 if(warning_flood || warning_list.tellp() >= 65000)
6250 {
6251 if(!warning_flood)
6252 warning_list << "...\n...\n...\nmany others";
6253 warning_flood = true;
6254 }
6255 else
6256 warning_list << ref->name << '\n';
6257 }
6258 }
6259 else if(i==ti_encompass)
6260 {
6261 move_refs.emplace_back(std::move(ref));
6262 return true;
6263 }
6264 }
6265 return false;
6266 }
6267
6268 bool ComboMoveList::check_prot()
6269 {
6270 if(!ComboProtection)
6271 return true;
6272 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6273 bool subset_header = false;
6274 for(int q = 0; q < 2; ++q)
6275 {
6276 bool is_dest = (q==1);
6277 if(!is_dest && !source_process)
6278 continue;
6279 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6280 for(auto it = subset.begin(); it != subset.end();)
6281 {
6282 auto s = *it;
6283 if(warning_flood || warning_list.tellp() >= 65000)
6284 {
6285 if(!warning_flood)
6286 warning_list << "...\n...\n...\nmany others";
6287 warning_flood = true;
6288 break;
6289 }
6290 set<int> in_set, out_set;
6291 bool no_move = is_dest;
6292 for(int c : *s)
6293 {
6294 int i = move_intersection_ss(c, c, proc._first, proc._last);
6295 if(i != ti_none)
6296 in_set.insert(c);
6297 if(i != ti_encompass)
6298 out_set.insert(c);
6299 if(!no_move)
6300 {
6301 auto it = processed_combos.find(c);
6302 if(it != processed_combos.end() && it->second)
6303 no_move = true;
6304 }
6305 }
6306 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6307 if(i == ti_encompass && !no_move)
6308 {
6309 it = subset.erase(it);
6310 continue;
6311 }
6312 if(i == ti_none)
6313 {
6314 ++it;
6315 continue;
6316 }
6317
6318 if(!subset_header)
6319 {
6320 subset_header = true;
6321 warning_list << "===== Broken Relative Combo Groups =====\n";
6322 }
6323 bool comma = false;
6324 warning_list << "In(";
6325 for(int c : in_set)
6326 {
6327 if(comma)
6328 warning_list << ",";
6329 else comma = true;
6330 warning_list << c;
6331 }
6332 warning_list << "),Out(";
6333 comma = false;
6334 for(int c : out_set)
6335 {
6336 if(comma)
6337 warning_list << ",";
6338 else comma = true;
6339 warning_list << c;
6340 }
6341 warning_list << ")\n";
6342 it = subset.erase(it);
6343 }
6344 }
6345 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6346
6347 processed_combos.clear();
6348 warning_flood = false;
6349 warning_list.clear();
6350
6351 return ret;
6352 }
6353
6354 void ComboMoveList::add_diff(int diff)
6355 {
6356 for(auto& ref : move_refs)
6357 ref->addCombo(diff);
6358 }
6359
6360 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6361 {
6362 bool BSZ2 = get_qr(qr_BSZELDA);
6363 bool move = source_process.has_value();
6364 TileMoveUndo local_undo;
6365 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6366 auto& vec = storage.vec;
6367 storage.diff = diff;
6368 storage.state = false;
6369
6370 //Combos
6371 {
6372 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6373 dest_process, source_process, mode,
6374 move
6375 ? "The tiles used by the following combos will be partially cleared by the move."
6376 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6377 ));
6378 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6379 {
6380 auto& cmb = combobuf[q];
6381 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6382 : fmt::format(" ({})", cmb.label));
6383 movelist->add_combo(&cmb, lbl);
6384
6385 //type-specific
6386 char const* type_name = ZI.getComboTypeName(cmb.type);
6387 switch(cmb.type)
6388 {
6389 case cSPOTLIGHT:
6390 {
6391 if(!(cmb.usrflags & cflag1))
6392 break;
6393 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6394 break;
6395 }
6396 }
6397 }
6398 if(!every_proc && !movelist->check_prot())
6399 return false;
6400 }
6401 //Items
6402 {
6403 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6404 dest_process, source_process, mode,
6405 move
6406 ? "The tiles used by the following items will be partially cleared by the move."
6407 : "The tiles used by the following items will be partially or completely overwritten by this process."
6408 ));
6409 build_bii_list(false);
6410 for(int32_t u=0; u<MAXITEMS; u++)
6411 {
6412 auto id = bii[u].i;
6413 itemdata& itm = itemsbuf[id];
6414 if(itm.family == itype_bottle)
6415 {
6416 vector<std::tuple<int,int,int>> rects;
6417 auto fr = itm.frames;
6418 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6419 {
6420 bottletype const& bt = QMisc.bottle_types[q];
6421 if(bt.is_blank())
6422 continue;
6423 rects.emplace_back(fr+q*fr, fr, 1);
6424 }
6425 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6426 false, 0, 0, rects);
6427 }
6428 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6429 }
6430 if(!every_proc && !movelist->check_prot())
6431 return false;
6432 }
6433 //Weapon sprites
6434 {
6435 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6436 dest_process, source_process, mode,
6437 move
6438 ? "The tiles used by the following weapons will be partially cleared by the move."
6439 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6440 ));
6441 build_biw_list();
6442
6443 for(int32_t u=0; u<MAXWPNS; u++)
6444 {
6445 bool ignore_frames=false;
6446 int32_t m=0;
6447
6448 auto id = biw[u].i;
6449 auto& wpn = wpnsbuf[id];
6450
6451 switch(biw[u].i)
6452 {
6453 case wSWORD:
6454 case wWSWORD:
6455 case wMSWORD:
6456 case wXSWORD:
6457 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6458 break;
6459
6460 case wSWORDSLASH:
6461 case wWSWORDSLASH:
6462 case wMSWORDSLASH:
6463 case wXSWORDSLASH:
6464 m=4;
6465 break;
6466
6467 case iwMMeter:
6468 m=9;
6469 break;
6470
6471 case wBRANG:
6472 case wMBRANG:
6473 case wFBRANG:
6474 m=BSZ2?1:3;
6475 break;
6476
6477 case wBOOM:
6478 case wSBOOM:
6479 case ewBOOM:
6480 case ewSBOOM:
6481 ignore_frames=true;
6482 m=2;
6483 break;
6484
6485 case wWAND:
6486 m=1;
6487 break;
6488
6489 case wMAGIC:
6490 m=1;
6491 break;
6492
6493 case wARROW:
6494 case wSARROW:
6495 case wGARROW:
6496 case ewARROW:
6497 m=1;
6498 break;
6499
6500 case wHAMMER:
6501 m=8;
6502 break;
6503
6504 case wHSHEAD:
6505 m=1;
6506 break;
6507
6508 case wHSCHAIN_H:
6509 m=1;
6510 break;
6511
6512 case wHSCHAIN_V:
6513 m=1;
6514 break;
6515
6516 case wHSHANDLE:
6517 m=1;
6518 break;
6519
6520 case iwDeath:
6521 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6522 {
6523 ignore_frames = true;
6524 m=BSZ2?4:2;
6525 }
6526 break;
6527
6528 case iwSpawn:
6529 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6530 {
6531 ignore_frames = true;
6532 m=3;
6533 }
6534 break;
6535 }
6536
6537 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6538 1, fmt::format("{} {}", biw[u].s, id));
6539
6540 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6541 //...these can't be updated by a move.
6542 if((u==3)||(u==9))
6543 {
6544 static int32_t impact_tiles[2] = {54,54};
6545 auto& tile = impact_tiles[u==3 ? 0 : 1];
6546 tile = 54; //dummy tile, ensure it's correct
6547 movelist->add_tile(&tile, 2, 1,
6548 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6549 true);
6550 }
6551 }
6552 if(!every_proc && !movelist->check_prot())
6553 return false;
6554 }
6555 //Player sprites
6556 {
6557 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6558 dest_process, source_process, mode,
6559 move
6560 ? "The tiles used by the following player sprites will be partially cleared by the move."
6561 : "The tiles used by the following player sprites will be partially or completely overwritten by this process."
6562 ));
6563 {
6564 int32_t a_style=(zinit.heroAnimationStyle);
6565 #define ADD_PLAYER_SPRITE(ref_sprite, frames, name) \
6566 do \
6567 { \
6568 movelist->add_tile(&ref_sprite[spr_tile], \
6569 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6570 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6571 name, false, \
6572 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6573 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6574 } while(false)
6575 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6576
6577 for(int32_t i=0; i<4; ++i)
6578 {
6579 ADD_PLAYER_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6580 }
6581
6582 for(int32_t i=0; i<4; ++i)
6583 {
6584 ADD_PLAYER_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6585 }
6586
6587 for(int32_t i=0; i<4; ++i)
6588 {
6589 ADD_PLAYER_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6590 }
6591
6592 for(int32_t i=0; i<4; ++i)
6593 {
6594 ADD_PLAYER_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6595 }
6596
6597 for(int32_t i=0; i<2; ++i)
6598 {
6599 ADD_PLAYER_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6600 }
6601
6602 ADD_PLAYER_SPRITE(castingspr, 1, "Casting");
6603
6604 for(int32_t i=0; i<4; ++i)
6605 {
6606 ADD_PLAYER_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6607 }
6608
6609 for(int32_t i=0; i<4; ++i)
6610 {
6611 ADD_PLAYER_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6612 }
6613
6614 for(int32_t i=0; i<4; ++i)
6615 {
6616 ADD_PLAYER_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6617 }
6618
6619 for(int32_t i=0; i<2; ++i)
6620 {
6621 ADD_PLAYER_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6622 }
6623
6624 for(int32_t i=0; i<4; ++i)
6625 {
6626 ADD_PLAYER_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6627 }
6628
6629 for(int32_t i=0; i<4; ++i)
6630 {
6631 ADD_PLAYER_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6632 }
6633 for(int32_t i=0; i<4; ++i)
6634 {
6635 ADD_PLAYER_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6636 }
6637 for(int32_t i=0; i<4; ++i)
6638 {
6639 ADD_PLAYER_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6640 }
6641 for(int32_t i=0; i<4; ++i)
6642 {
6643 ADD_PLAYER_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6644 }
6645 for(int32_t i=0; i<4; ++i)
6646 {
6647 ADD_PLAYER_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6648 }
6649 for(int32_t i=0; i<4; ++i)
6650 {
6651 ADD_PLAYER_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6652 }
6653 for(int32_t i=0; i<4; ++i)
6654 {
6655 ADD_PLAYER_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6656 }
6657 for(int32_t i=0; i<4; ++i)
6658 {
6659 ADD_PLAYER_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6660 }
6661 //69
6662 for(int32_t i=0; i<4; ++i)
6663 {
6664 ADD_PLAYER_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6665 }
6666 //73
6667 for(int32_t i=0; i<4; ++i)
6668 {
6669 ADD_PLAYER_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6670 }
6671 //77
6672 for(int32_t i=0; i<4; ++i)
6673 {
6674 ADD_PLAYER_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6675 }
6676 //81
6677 for(int32_t i=0; i<4; ++i)
6678 {
6679 ADD_PLAYER_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6680 }
6681 //85
6682 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6683 ADD_PLAYER_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6684 ADD_PLAYER_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6685 for(int32_t i=0; i<4; ++i)
6686 {
6687 ADD_PLAYER_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6688 }
6689 //91
6690 }
6691 if(!every_proc && !movelist->check_prot())
6692 return false;
6693 }
6694 //Map Styles
6695 {
6696 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6697 dest_process, source_process, mode,
6698 move
6699 ? "The tiles used by the following map styles will be partially cleared by the move."
6700 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6701 ));
6702 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6703 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6704 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6705 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6706 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6707 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6708 if(!every_proc && !movelist->check_prot())
6709 return false;
6710 }
6711 //Game Icons
6712 {
6713 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6714 dest_process, source_process, mode,
6715 move
6716 ? "The tiles used by the following game icons will be partially cleared by the move."
6717 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6718 ));
6719 for(int32_t u=0; u<4; u++)
6720 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6721 if(!every_proc && !movelist->check_prot())
6722 return false;
6723 }
6724 //DMaps
6725 {
6726 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6727 dest_process, source_process, mode,
6728 move
6729 ? "The tiles used by the following dmaps will be partially cleared by the move."
6730 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6731 ));
6732 for(int32_t u=0; u<MAXDMAPS; u++)
6733 {
6734 auto& dm = DMaps[u];
6735 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6736 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6737 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6738 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6739 }
6740 if(!every_proc && !movelist->check_prot())
6741 return false;
6742 }
6743 //Enemies
6744 {
6745 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6746 dest_process, source_process, mode,
6747 move
6748 ? "The tiles used by the following enemies will be partially cleared by the move."
6749 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6750 ));
6751 build_bie_list(false);
6752 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6753 for(int u=0; u<eMAXGUYS; u++)
6754 {
6755 guydata& enemy=guysbuf[bie[u].i];
6756 bool darknut=false;
6757 int32_t gleeok=0;
6758
6759 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6760 darknut=true;
6761 else if(enemy.family==eeGLEEOK)
6762 {
6763 // Not certain this is the right thing to check...
6764 if(enemy.attributes[2] == 0)
6765 gleeok=1;
6766 else
6767 gleeok=2;
6768 }
6769
6770 // Dummied out enemies
6771 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6772 {
6773 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6774 {
6775 continue;
6776 }
6777 }
6778
6779 if(newtiles)
6780 {
6781 if(guysbuf[bie[u].i].e_tile==0)
6782 {
6783 continue;
6784 }
6785
6786 vector<std::tuple<int,int,int>> rects;
6787
6788 if(darknut)
6789 {
6790 rects.emplace_back(enemy.e_tile+6*TILES_PER_ROW, enemy.e_width, enemy.e_height);
6791 }
6792 else if(enemy.family==eeGANON)
6793 {
6794 rects.emplace_back(enemy.e_tile+2*TILES_PER_ROW, 20, 4);
6795 }
6796 else if(gleeok) //No idea if this is actually *RIGHT*, but I copied what was here before faithfully -Em
6797 {
6798 for(int32_t j=0; j<4; ++j)
6799 {
6800 rects.emplace_back(
6801 TILECOL(guysbuf[bie[u].i].e_tile+(gleeok>1?-4:8)) + TILES_PER_ROW*TILEROW(guysbuf[bie[u].i].e_tile+8)+(j<<1)+(gleeok>1?1:0),
6802 4, 1);
6803 }
6804 int32_t c=TILECOL(guysbuf[bie[u].i].e_tile)+(gleeok>1?-12:0);
6805 int32_t r=TILEROW(guysbuf[bie[u].i].e_tile)+(gleeok>1?17:8);
6806 rects.emplace_back(c+TILES_PER_ROW*r, 20, 3);
6807 rects.emplace_back(c+TILES_PER_ROW*(r+3), 16, 6);
6808 }
6809 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6810 false, 0, 0, rects);
6811 }
6812 else
6813 {
6814 if(guysbuf[bie[u].i].tile==0)
6815 {
6816 continue;
6817 }
6818 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6819
6820 if(guysbuf[bie[u].i].s_tile!=0)
6821 {
6822 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6823 }
6824 }
6825 }
6826 if(!every_proc && !movelist->check_prot())
6827 return false;
6828 }
6829 //Subscreens
6830 {
6831 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6832 dest_process, source_process, mode,
6833 move
6834 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6835 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6836 ));
6837
6838 for(auto q = 0; q < subscreens_active.size(); ++q)
6839 {
6840 size_t indx = movelist->move_refs.size();
6841 subscreens_active[q].collect_tiles(*movelist.get());
6842 for(; indx < movelist->move_refs.size(); ++indx)
6843 {
6844 auto& ref = movelist->move_refs[indx];
6845 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6846 }
6847 }
6848 for(auto q = 0; q < subscreens_passive.size(); ++q)
6849 {
6850 size_t indx = movelist->move_refs.size();
6851 subscreens_passive[q].collect_tiles(*movelist.get());
6852 for(; indx < movelist->move_refs.size(); ++indx)
6853 {
6854 auto& ref = movelist->move_refs[indx];
6855 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6856 }
6857 }
6858 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6859 {
6860 size_t indx = movelist->move_refs.size();
6861 subscreens_overlay[q].collect_tiles(*movelist.get());
6862 for(; indx < movelist->move_refs.size(); ++indx)
6863 {
6864 auto& ref = movelist->move_refs[indx];
6865 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6866 }
6867 }
6868 if(!every_proc && !movelist->check_prot())
6869 return false;
6870 }
6871 //Strings
6872 {
6873 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6874 dest_process, source_process, mode,
6875 move
6876 ? "The tiles used by the following strings will be partially cleared by the move."
6877 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6878 ));
6879 for(size_t q = 0; q < msg_count; ++q)
6880 {
6881 MsgStr& str = MsgStrings[q];
6882 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6883 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6884 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6885 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6886 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6887 }
6888 if(!every_proc && !movelist->check_prot())
6889 return false;
6890 }
6891
6892 if(source_process) //Apply the 'diff' value to all moved tiles
6893 storage.redo();
6894 if(every_proc)
6895 for(auto &list : vec)
6896 for(auto &ref : list->move_refs)
6897 ref->forEach(every_proc);
6898 return true;
6899 }
6900 bool handle_tile_move(TileMoveProcess dest_process)
6901 {
6902 return _handle_tile_move(dest_process, nullopt, 0);
6903 }
6904 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6905 {
6906 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6907 }
6908 void for_every_used_tile(std::function<void(int32_t)> proc)
6909 {
6910 reset_combo_animations();
6911 reset_combo_animations2();
6912 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6913 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6914 }
6915
6916 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6917 {
6918 bool BSZ2 = get_qr(qr_BSZELDA);
6919 bool move = source_process.has_value();
6920 ComboMoveUndo local_undo;
6921 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6922 auto& vec = storage.vec;
6923 auto& combo_links = storage.combo_links;
6924 storage.diff = diff;
6925 storage.state = false;
6926 //Combo relative links
6927 {
6928 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6929 {
6930 newcombo& cmb = combobuf[q];
6931 if(cmb.trigchange)
6932 combo_links.add_to(q, q+cmb.trigchange);
6933 bool next = cmb.flag == mfSECRETSNEXT;
6934 switch(cmb.type)
6935 {
6936 case cPOUND:
6937 case cLOCKBLOCK: case cLOCKBLOCK2:
6938 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
6939 case cCHEST: case cCHEST2:
6940 case cLOCKEDCHEST: case cLOCKEDCHEST2:
6941 case cBOSSCHEST: case cBOSSCHEST2:
6942 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
6943 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
6944 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
6945 case cTALLGRASSNEXT: case cCRUMBLE:
6946 next = true;
6947 break;
6948 case cCSWITCH: case cCSWITCHBLOCK:
6949 combo_links.add_to(q, q+cmb.attributes[0]);
6950 break;
6951 case cLIGHTTARGET:
6952 if(cmb.usrflags & cflag1)
6953 combo_links.add_to(q, q-1);
6954 else next = true;
6955 break;
6956 case cSTEPSFX:
6957 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
6958 next = true;
6959 break;
6960 }
6961 if(next)
6962 combo_links.add_to(q, q+1);
6963 }
6964 }
6965
6966 //This function is expensive! Any optimizations possible should be made. -Em
6967
6968 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
6969 #define ADDC(ptr, ...) \
6970 if(*ptr) movelist->add_combo(ptr, __VA_ARGS__);
6971 #define ADDC_10k(ptr, ...) \
6972 if(*ptr) movelist->add_combo_10k(ptr, __VA_ARGS__);
6973 //Combos
6974 {
6975 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
6976 combo_links, dest_process, source_process,
6977 move
6978 ? "The combos used by the following combos will be partially cleared by the move."
6979 : "The combos used by the following combos will be partially or completely overwritten by this process."
6980 ));
6981 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6982 {
6983 newcombo& cmb = combobuf[q];
6984 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
6985 : fmt::format(" ({})", cmb.label));
6986 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
6987 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
6988 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
6989 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
6990
6991 //type-specific
6992 char const* type_name = ZI.getComboTypeName(cmb.type);
6993 switch(cmb.type)
6994 {
6995 case cLOCKEDCHEST: case cBOSSCHEST:
6996 if(cmb.usrflags & cflag13)
6997 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
6998 [[fallthrough]];
6999 case cCHEST:
7000 if(cmb.usrflags & cflag13)
7001 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7002 break;
7003 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7004 if(cmb.usrflags & cflag13)
7005 {
7006 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7007 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7008 }
7009 break;
7010 case cSIGNPOST:
7011 if(cmb.usrflags & cflag13)
7012 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7013 break;
7014 case cBUTTONPROMPT:
7015 if(cmb.usrflags & cflag13)
7016 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7017 break;
7018 }
7019 }
7020
7021 if(!movelist->check_prot())
7022 return false;
7023 }
7024 //Door Combo Sets
7025 {
7026 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7027 combo_links, dest_process, source_process,
7028 move
7029 ? "The combos used by the following screens will be partially cleared by the move."
7030 : "The combos used by the following screens will be partially or completely overwritten by this process."
7031 ));
7032 static const char* door_names[9] = {
7033 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7034 };
7035 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7036 {
7037 auto& dcs = DoorComboSets[i];
7038 for(int32_t j=0; j<9; j++)
7039 {
7040 if(j<4)
7041 {
7042 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, dcs.name, j));
7043
7044 if(j<3)
7045 {
7046 if(j<2)
7047 {
7048 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, dcs.name, j));
7049 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, dcs.name, j));
7050 }
7051 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, dcs.name, j));
7052 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, dcs.name, j));
7053 }
7054 }
7055
7056 for(int32_t k=0; k<6; k++)
7057 {
7058 if(k<4)
7059 {
7060 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, dcs.name, door_names[j], k));
7061 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, dcs.name, door_names[j], k));
7062 }
7063
7064 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, dcs.name, door_names[j], k));
7065 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, dcs.name, door_names[j], k));
7066 }
7067 }
7068 }
7069
7070 if(!movelist->check_prot())
7071 return false;
7072 }
7073 //Combo Pools
7074 {
7075 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7076 combo_links, dest_process, source_process,
7077 move
7078 ? "The combos used by the following combo pools will be partially cleared by the move."
7079 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7080 ));
7081 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7082 {
7083 combo_pool& pool = combo_pools[q];
7084 int idx = 0;
7085 for(cpool_entry& cp : pool.combos)
7086 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7087 }
7088
7089 if(!movelist->check_prot())
7090 return false;
7091 }
7092 //Auto Combos
7093 {
7094 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7095 combo_links, dest_process, source_process,
7096 move
7097 ? "The combos used by the following autocombos will be partially cleared by the move."
7098 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7099 ));
7100 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7101 {
7102 combo_auto& cauto = combo_autos[q];
7103 int idx = 0;
7104 for (autocombo_entry& ac : cauto.combos)
7105 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7106 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7107 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7108 }
7109
7110 if(!movelist->check_prot())
7111 return false;
7112 }
7113 //Combo Aliases
7114 {
7115 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7116 combo_links, dest_process, source_process,
7117 move
7118 ? "The combos used by the following aliases will be partially cleared by the move."
7119 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7120 ));
7121 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7122 {
7123 //dimensions are 1 less than you would expect -DD
7124 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7125
7126 for(int32_t j=0; j<count; j++)
7127 {
7128 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7129 }
7130 }
7131
7132 if(!movelist->check_prot())
7133 return false;
7134 }
7135 //Favorite Combos
7136 {
7137 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7138 combo_links, dest_process, source_process,
7139 move
7140 ? "The combos used by the following favorite combos will be partially cleared by the move."
7141 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7142 ));
7143 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7144 {
7145 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7146 continue;
7147 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7148 }
7149
7150 if(!movelist->check_prot())
7151 return false;
7152 }
7153 //Bottle Shops
7154 {
7155 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7156 combo_links, dest_process, source_process,
7157 move
7158 ? "The combos used by the following bottle shops will be partially cleared by the move."
7159 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7160 ));
7161 for(auto q = 0; q < 256; ++q)
7162 for(auto p = 0; p < 3; ++p)
7163 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7164
7165 if(!movelist->check_prot())
7166 return false;
7167 }
7168 //Screens //EXPENSIVE! DO THIS LAST!
7169 {
7170 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7171 combo_links, dest_process, source_process,
7172 move
7173 ? "The combos used by the following screens will be partially cleared by the move."
7174 : "The combos used by the following screens will be partially or completely overwritten by this process."
7175 ));
7176
7177 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7178 {
7179 for(int32_t j=0; j<MAPSCRS; j++)
7180 {
7181 mapscr& scr = TheMaps[i*MAPSCRS+j];
7182
7183 if(!(scr.valid&mVALID))
7184 continue;
7185
7186 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7187 for(int32_t k=0; k<176; k++)
7188 ADDC(&scr.data[k], fmt::format("{}x{:02X} - Pos {}", i, j, k));
7189
7190 for(int32_t k=0; k<128; k++)
7191 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7192
7193 word maxffc = scr.numFFC();
7194 for(word k=0; k<maxffc; k++)
7195 {
7196 ffcdata& ffc = scr.ffcs[k];
7197 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7198 }
7199 }
7200 }
7201
7202 if(!movelist->check_prot())
7203 return false;
7204 }
7205 if(source_process) //Apply the 'diff' value to all moved combos
7206 storage.redo();
7207 return true;
7208 }
7209
7210 bool handle_combo_move(ComboMoveProcess dest_process)
7211 {
7212 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7213 }
7214 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7215 {
7216 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7217 }
7218 void register_used_tiles()
7219 {
7220 memset(used_tile_table, 0, sizeof(used_tile_table));
7221 for_every_used_tile([&](int tile)
7222 {
7223 used_tile_table[tile] = true;
7224 });
7225 }
7226
7227 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7228 {
7229 bool ctrl=(CHECK_CTRL_CMD);
7230 bool copied=false;
7231 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7232
7233 if(copied)
7234 {
7235 saved=false;
7236 }
7237
7238 return copied;
7239 }
7240
7241 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7242 {
7243 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7244 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7245
7246 // if tile>tile2 then swap them
7247 if(tile>tile2)
7248 {
7249 zc_swap(tile, tile2);
7250 }
7251
7252 // alt=copy from right
7253 // shift=copy from bottom
7254
7255 int32_t copies=copycnt;
7256 int32_t dest_first=tile;
7257 int32_t dest_last=tile2;
7258 int32_t src_first=copy;
7259 int32_t src_last=copy+copies-1;
7260
7261 int32_t dest_top=0;
7262 int32_t dest_bottom=0;
7263 int32_t src_top=0;
7264 int32_t src_bottom=0;
7265 int32_t src_left=0, src_right=0;
7266 int32_t src_width=0, src_height=0;
7267 int32_t dest_left=0, dest_right=0;
7268 int32_t dest_width=0, dest_height=0;
7269 int32_t rows=0, cols=0;
7270
7271 if(rect)
7272 {
7273 dest_top=TILEROW(dest_first);
7274 dest_bottom=TILEROW(dest_last);
7275 src_top=TILEROW(src_first);
7276 src_bottom=TILEROW(src_last);
7277
7278 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7279 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7280 src_first=(src_top * TILES_PER_ROW)+src_left;
7281 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7282
7283 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7284 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7285 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7286 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7287
7288 //if no dest range set, then set one
7289 if((dest_first==dest_last)&&(src_first!=src_last))
7290 {
7291 if(alt)
7292 {
7293 dest_left=dest_right-(src_right-src_left);
7294 }
7295 else
7296 {
7297 dest_right=dest_left+(src_right-src_left);
7298 }
7299
7300 if(shift)
7301 {
7302 dest_top=dest_bottom-(src_bottom-src_top);
7303 }
7304 else
7305 {
7306 dest_bottom=dest_top+(src_bottom-src_top);
7307 }
7308
7309 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7310 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7311 }
7312 else
7313 {
7314 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7315 {
7316 if(alt) //copy from right tile instead of left
7317 {
7318 src_left=src_right-(dest_right-dest_left);
7319 }
7320 else //copy from left tile
7321 {
7322 src_right=src_left+(dest_right-dest_left);
7323 }
7324 }
7325 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7326 {
7327 if(alt) //copy from right tile instead of left
7328 {
7329 dest_left=dest_right-(src_right-src_left);
7330 }
7331 else //copy from left tile
7332 {
7333 dest_right=dest_left+(src_right-src_left);
7334 }
7335 }
7336
7337 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7338 {
7339 if(shift) //copy from bottom tile instead of top
7340 {
7341 src_top=src_bottom-(dest_bottom-dest_top);
7342 }
7343 else //copy from top tile
7344 {
7345 src_bottom=src_top+(dest_bottom-dest_top);
7346 }
7347 }
7348 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7349 {
7350 if(shift) //copy from bottom tile instead of top
7351 {
7352 dest_top=dest_bottom-(src_bottom-src_top);
7353 }
7354 else //copy from top tile
7355 {
7356 dest_bottom=dest_top+(src_bottom-src_top);
7357 }
7358 }
7359
7360 src_first=(src_top * TILES_PER_ROW)+src_left;
7361 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7362 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7363 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7364 }
7365
7366 cols=src_right-src_left+1;
7367 rows=src_bottom-src_top+1;
7368
7369 dest_width=dest_right-dest_left+1;
7370 dest_height=dest_bottom-dest_top+1;
7371 src_width=src_right-src_left+1;
7372 src_height=src_bottom-src_top+1;
7373
7374 }
7375 else //!rect
7376 {
7377 //if no dest range set, then set one
7378 if((dest_first==dest_last)&&(src_first!=src_last))
7379 {
7380 if(alt)
7381 {
7382 dest_first=dest_last-(src_last-src_first);
7383 }
7384 else
7385 {
7386 dest_last=dest_first+(src_last-src_first);
7387 }
7388 }
7389 else
7390 {
7391 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7392 {
7393 if(alt) //copy from last tile instead of first
7394 {
7395 src_first=src_last-(dest_last-dest_first);
7396 }
7397 else //copy from first tile
7398 {
7399 src_last=src_first+(dest_last-dest_first);
7400 }
7401 }
7402 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7403 {
7404 if(alt) //copy from last tile instead of first
7405 {
7406 dest_first=dest_last-(src_last-src_first);
7407 }
7408 else //copy from first tile
7409 {
7410 dest_last=dest_first+(src_last-src_first);
7411 }
7412 }
7413 }
7414
7415 copies=dest_last-dest_first+1;
7416 }
7417
7418
7419
7420 char buf2[80], buf3[80], buf4[80];
7421 sprintf(buf2, " ");
7422 sprintf(buf3, " ");
7423 sprintf(buf4, " ");
7424
7425 // warn if range extends beyond last tile
7426 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7427
7428 if(dest_last>=NEWMAXTILES)
7429 {
7430 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7431 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7432 return false;
7433 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7434 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7435 // {
7436 // return false;
7437 // }
7438 }
7439
7440
7441 TileMoveUndo on_undo;
7442 // Overwrite warnings
7443 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7444 if(move)
7445 {
7446 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7447 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7448 return false;
7449 }
7450 else
7451 {
7452 if(!handle_tile_move(dest))
7453 return false;
7454 }
7455 // copy tiles and delete if needed (move)
7456
7457 {
7458 go_tiles();
7459
7460 int32_t diff=dest_first-src_first;
7461
7462 if(rect)
7463 {
7464 for(int32_t r=0; r<rows; ++r)
7465 {
7466 for(int32_t c=0; c<cols; ++c)
7467 {
7468 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7469 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7470
7471 if(dt>=NEWMAXTILES)
7472 continue;
7473
7474 overlay_tile(newtilebuf,dt,st,cs,backwards);
7475
7476 }
7477 }
7478 }
7479 else
7480 {
7481 for(int32_t c=0; c<copies; ++c)
7482 {
7483 int32_t dt=(dest_first+c);
7484 int32_t st=(src_first+c);
7485
7486 if(dt>=NEWMAXTILES)
7487 continue;
7488
7489 overlay_tile(newtilebuf,dt,st,cs,backwards);
7490
7491 if(move)
7492 {
7493 if(st<dest_first||st>(dest_first+c-1))
7494 reset_tile(newtilebuf, st, tf4Bit);
7495 }
7496 }
7497 }
7498 }
7499
7500 //now that tiles have moved, fix these buffers -DD
7501 register_blank_tiles();
7502 register_used_tiles();
7503
7504 if(move)
7505 last_tile_move_list = std::move(on_undo);
7506 return true;
7507 }
7508 //
7509 bool do_movetile_united(tile_move_data const& tmd)
7510 {
7511 char buf2[80], buf3[80], buf4[80];
7512 sprintf(buf2, " ");
7513 sprintf(buf3, " ");
7514 sprintf(buf4, " ");
7515
7516 // warn if range extends beyond last tile
7517 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7518
7519 if(tmd.dest_last>=NEWMAXTILES)
7520 {
7521 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7522 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7523 return false;
7524 }
7525
7526 TileMoveUndo on_undo;
7527 // Overwrite warnings
7528 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7529 if(tmd.move)
7530 {
7531 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7532 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7533 return false;
7534 }
7535 else
7536 {
7537 if(!handle_tile_move(dest))
7538 return false;
7539 }
7540
7541 // copy tiles and delete if needed (tmd.move)
7542 {
7543 go_tiles();
7544
7545 if(tmd.rect)
7546 {
7547 for(int32_t r=0; r<tmd.rows; ++r)
7548 {
7549 for(int32_t c=0; c<tmd.cols; ++c)
7550 {
7551 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7552 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7553
7554 if(dt>=NEWMAXTILES)
7555 continue;
7556
7557 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7558
7559 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7560 {
7561 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7562 }
7563
7564 if(tmd.move)
7565 {
7566 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7567 reset_tile(newtilebuf, st, tf4Bit);
7568 else
7569 {
7570 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7571 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7572 if(destLeft<=destRight)
7573 {
7574 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7575 reset_tile(newtilebuf, st, tf4Bit);
7576 }
7577 else // Wrapped around
7578 {
7579 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7580 reset_tile(newtilebuf, st, tf4Bit);
7581 }
7582 }
7583 }
7584 }
7585 }
7586 }
7587 else
7588 {
7589 for(int32_t c=0; c<tmd.copies; ++c)
7590 {
7591 int32_t dt=(tmd.dest_first+c);
7592 int32_t st=(tmd.src_first+c);
7593
7594 if(dt>=NEWMAXTILES)
7595 continue;
7596
7597 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7598
7599 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7600 {
7601 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7602 }
7603
7604 if(tmd.move)
7605 {
7606 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7607 reset_tile(newtilebuf, st, tf4Bit);
7608 }
7609 }
7610 }
7611 }
7612
7613 //now that tiles have moved, fix these buffers -DD
7614 register_blank_tiles();
7615 register_used_tiles();
7616
7617 if(tmd.move)
7618 last_tile_move_list = std::move(on_undo);
7619 return true;
7620 }
7621
7622 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7623 {
7624 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7625 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7626
7627 // if tile>tile2 then swap them
7628 if(tile>tile2)
7629 {
7630 zc_swap(tile, tile2);
7631 }
7632
7633 // alt=copy from right
7634 // shift=copy from bottom
7635 tile_move_data tmd;
7636
7637 tmd.copies=copycnt;
7638 tmd.dest_first=tile;
7639 tmd.dest_last=tile2;
7640 tmd.src_first=copy;
7641 tmd.src_last=copy+tmd.copies-1;
7642 tmd.rect = rect;
7643 tmd.move = move;
7644
7645 if(rect)
7646 {
7647 tmd.dest_top=TILEROW(tmd.dest_first);
7648 tmd.dest_bottom=TILEROW(tmd.dest_last);
7649 tmd.src_top=TILEROW(tmd.src_first);
7650 tmd.src_bottom=TILEROW(tmd.src_last);
7651
7652 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7653 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7654 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7655 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7656
7657 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7658 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7659 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7660 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7661
7662 //if no dest range set, then set one
7663 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7664 {
7665 if(alt)
7666 {
7667 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7668 }
7669 else
7670 {
7671 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7672 }
7673
7674 if(shift)
7675 {
7676 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7677 }
7678 else
7679 {
7680 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7681 }
7682
7683 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7684 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7685 }
7686 else
7687 {
7688 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7689 {
7690 if(alt) //copy from right tile instead of left
7691 {
7692 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7693 }
7694 else //copy from left tile
7695 {
7696 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7697 }
7698 }
7699 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7700 {
7701 if(alt) //copy from right tile instead of left
7702 {
7703 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7704 }
7705 else //copy from left tile
7706 {
7707 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7708 }
7709 }
7710
7711 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7712 {
7713 if(shift) //copy from bottom tile instead of top
7714 {
7715 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7716 }
7717 else //copy from top tile
7718 {
7719 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7720 }
7721 }
7722 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7723 {
7724 if(shift) //copy from bottom tile instead of top
7725 {
7726 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7727 }
7728 else //copy from top tile
7729 {
7730 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7731 }
7732 }
7733
7734 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7735 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7736 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7737 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7738 }
7739
7740 tmd.cols=tmd.src_right-tmd.src_left+1;
7741 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7742
7743 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7744 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7745 tmd.src_width=tmd.src_right-tmd.src_left+1;
7746 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7747
7748 }
7749 else //!rect
7750 {
7751 //if no dest range set, then set one
7752 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7753 {
7754 if(alt)
7755 {
7756 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7757 }
7758 else
7759 {
7760 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7761 }
7762 }
7763 else
7764 {
7765 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7766 {
7767 if(alt) //copy from last tile instead of first
7768 {
7769 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7770 }
7771 else //copy from first tile
7772 {
7773 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7774 }
7775 }
7776 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7777 {
7778 if(alt) //copy from last tile instead of first
7779 {
7780 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7781 }
7782 else //copy from first tile
7783 {
7784 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7785 }
7786 }
7787 }
7788
7789 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7790 }
7791
7792 return do_movetile_united(tmd);
7793 }
7794
7795 //
7796
7797 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7798 {
7799 assert(!move); //not implemented
7800
7801 // if tile>tile2 then swap them
7802 if(tile>tile2)
7803 {
7804 zc_swap(tile, tile2);
7805 }
7806
7807 tile_move_data tmd;
7808 tmd.copies=copycnt;
7809 tmd.dest_first=tile;
7810 tmd.dest_last=tile2;
7811 tmd.src_first=copy;
7812 tmd.src_last=copy+tmd.copies-1;
7813
7814
7815
7816 if(rect)
7817 {
7818 tmd.dest_top=TILEROW(tmd.dest_first);
7819 tmd.dest_bottom=TILEROW(tmd.dest_last);
7820 //tmd.src_top=TILEROW(tmd.src_first);
7821 //tmd.src_bottom=TILEROW(tmd.src_last);
7822
7823 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7824 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7825 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7826 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7827
7828 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7829 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7830 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7831 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7832
7833
7834
7835
7836 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7837 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7838
7839 tmd.cols=tmd.dest_width+1;
7840 tmd.rows=tmd.dest_height+1;
7841
7842 al_trace("tmd.rows: %d\n", tmd.rows);
7843 al_trace("tmd.cols: %d\n", tmd.cols);
7844
7845
7846 }
7847 else //!rect
7848 {
7849 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7850 }
7851
7852
7853
7854 char buf2[80], buf3[80], buf4[80];
7855 sprintf(buf2, " ");
7856 sprintf(buf3, " ");
7857 sprintf(buf4, " ");
7858
7859 // warn if range extends beyond last tile
7860 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7861
7862 if(tmd.dest_last>=NEWMAXTILES)
7863 {
7864 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7865 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7866 return false;
7867 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7868 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7869 // {
7870 // return false;
7871 // }
7872 }
7873
7874 TileMoveUndo on_undo;
7875 // Overwrite warnings
7876 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7877 if(tmd.move)
7878 {
7879 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7880 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7881 return false;
7882 }
7883 else
7884 {
7885 if(!handle_tile_move(dest))
7886 return false;
7887 }
7888
7889 // copy tiles and delete if needed (move)
7890
7891 {
7892 go_tiles();
7893
7894 int32_t diff=tmd.dest_first-tmd.src_first;
7895
7896 if(rect)
7897 {
7898 al_trace("floodfill, rect\n");
7899 al_trace("tmd.rows: %d\n", tmd.rows);
7900 al_trace("tmd.cols: %d\n", tmd.cols);
7901 for(int32_t r=0; r<tmd.rows; ++r)
7902 {
7903 for(int32_t c=0; c<tmd.cols; ++c)
7904 {
7905 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7906 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7907
7908 if(dt>=NEWMAXTILES)
7909 continue;
7910
7911 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7912
7913 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7914 {
7915 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7916 }
7917 }
7918 }
7919 }
7920 else
7921 {
7922 for(int32_t c=0; c<tmd.copies; ++c)
7923 {
7924 int32_t dt=(tmd.dest_first+c);
7925 int32_t st=(tmd.src_first+c);
7926
7927 if(dt>=NEWMAXTILES)
7928 continue;
7929
7930 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7931
7932 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7933 {
7934 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7935 }
7936
7937 }
7938 }
7939 }
7940
7941 //now that tiles have moved, fix these buffers -DD
7942 register_blank_tiles();
7943 register_used_tiles();
7944
7945 if(tmd.move)
7946 last_tile_move_list = std::move(on_undo);
7947 return true;
7948 }
7949 //
7950
7951 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7952 {
7953 al_trace("Floodfill Psste\n");
7954 bool ctrl=(CHECK_CTRL_CMD);
7955 bool copied=false;
7956 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
7957
7958 if(copied)
7959 {
7960 if(!ctrl)
7961 {
7962 copy=-1;
7963 tile2=tile;
7964 }
7965
7966 saved=false;
7967 }
7968
7969 return copied;
7970 }
7971
7972 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
7973 {
7974 bool ctrl=(CHECK_CTRL_CMD);
7975 bool copied=false;
7976 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
7977
7978 if(copied)
7979 {
7980 if(!ctrl)
7981 {
7982 copy=-1;
7983 tile2=tile;
7984 }
7985
7986 saved=false;
7987 }
7988
7989 return copied;
7990 }
7991
7992 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
7993 {
7994 // if tile>tile2 then swap them
7995 if(tile>tile2)
7996 {
7997 zc_swap(tile, tile2);
7998 }
7999 int32_t src_top = TILEROW(tile);
8000 int32_t src_bottom = TILEROW(tile2);
8001 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8002 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8003 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8004 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8005
8006 int32_t src_width = src_right-src_left+1,
8007 src_height = src_bottom-src_top+1;
8008 int32_t dest_width = src_width, dest_height = src_height;
8009 zfix dest_rot = 0_zf;
8010 if(rotate)
8011 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8012 else
8013 ScaleTileDialog(&dest_width, &dest_height).show();
8014 if (rotate)
8015 {
8016 if (dest_rot == 0) return false;
8017 }
8018 else
8019 {
8020 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8021 }
8022 dest_width = vbound(dest_width, 1, 20);
8023 dest_height = vbound(dest_height, 1, 20);
8024
8025 int32_t dest_top = src_top;
8026 int32_t dest_bottom = src_top+dest_height-1;
8027 int32_t dest_left = src_left;
8028 int32_t dest_right = src_left+dest_width-1;
8029 int32_t dest_first = src_first;
8030 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8031
8032
8033 if(dest_last>=NEWMAXTILES)
8034 {
8035 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8036 return false;
8037 }
8038
8039 // Overwrite warnings
8040 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8041 return false;
8042
8043 //Do the rotate
8044 {
8045 go_tiles();
8046
8047 int32_t diff=dest_first-src_first;
8048 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8049 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8050 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8051 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8052 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8053 if (rotate)
8054 {
8055 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8056 }
8057 else
8058 {
8059 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8060 0, 0, destbmp->w, destbmp->h);
8061 }
8062 int32_t mhei = zc_max(src_height,dest_height),
8063 mwid = zc_max(src_width, dest_width);
8064 for(int32_t r=0; r<mhei; ++r)
8065 {
8066 for(int32_t c=0; c<mwid; ++c)
8067 {
8068 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8069
8070 if(dt>=NEWMAXTILES)
8071 continue;
8072 if(r < dest_height && c < dest_width)
8073 {
8074 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8075 }
8076 else reset_tile(newtilebuf, dt, tf4Bit);
8077 }
8078 }
8079 }
8080
8081 register_blank_tiles();
8082 register_used_tiles();
8083 return true;
8084 }
8085
8086 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8087 {
8088 //these 2 shouldn't be needed, but just to be safe...
8089 reset_combo_animations();
8090 reset_combo_animations2();
8091
8092 if(tile2<tile)
8093 {
8094 zc_swap(tile,tile2);
8095 }
8096
8097 auto first = tile;
8098 auto last = masscopy ? tile2 : first + copycnt-1;
8099 if(!handle_combo_move({first,last}))
8100 return;
8101
8102 if(!masscopy)
8103 {
8104 if(tile==copy)
8105 {
8106 copy=-1;
8107 tile2=tile;
8108 return;
8109 }
8110
8111 // go_combos(); // commented because caller does it for us
8112 //if copying to an earlier combo, copy from left to right
8113 //otherwise, copy from right to left
8114 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8115 {
8116 if(tile+t < MAXCOMBOS)
8117 {
8118 combobuf[tile+t]=combobuf[copy+t];
8119 }
8120 }
8121
8122 copy=-1;
8123 tile2=tile;
8124 saved=false;
8125 }
8126 else
8127 {
8128 // go_combos();
8129 int32_t src=copy, dest=tile;
8130
8131 do
8132 {
8133 combobuf[dest]=combobuf[src];
8134 ++src;
8135 ++dest;
8136
8137 if((src-copy)==copycnt) src=copy;
8138 }
8139 while(dest<=tile2);
8140
8141 copy=-1;
8142 tile2=tile;
8143 saved=false;
8144 }
8145
8146 setup_combo_animations();
8147 setup_combo_animations2();
8148 }
8149
8150 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8151 {
8152 reset_combo_animations();
8153 reset_combo_animations2();
8154 go_combos();
8155
8156 auto diff = cmd.tile - cmd.copy1;
8157 if(is_undoing)
8158 on_undo.undo();
8159 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8160 return false;
8161
8162 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8163 {
8164 if(cmd.tile+t < MAXCOMBOS)
8165 {
8166 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8167 clear_combo(cmd.copy1+t);
8168 }
8169 }
8170
8171 setup_combo_animations();
8172 setup_combo_animations2();
8173 saved=false;
8174 return true;
8175 }
8176
8177 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8178 {
8179 if(tile2<tile)
8180 {
8181 zc_swap(tile,tile2);
8182 }
8183
8184 if(tile==copy)
8185 {
8186 copy=-1;
8187 tile2=tile;
8188 return;
8189 }
8190
8191 combo_move_data cmd;
8192 cmd.tile = tile;
8193 cmd.tile2 = tile2;
8194 cmd.copy1 = copy;
8195 cmd.copycnt = copycnt;
8196
8197 ComboMoveUndo on_undo;
8198 if(!do_movecombo(cmd, on_undo))
8199 return;
8200 last_combo_move_list = std::move(on_undo);
8201 copy=-1;
8202 tile2=tile;
8203 }
8204
8205 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8206 {
8207 if(firsttile > lasttile)
8208 zc_swap(firsttile,lasttile);
8209 int32_t coldiff = 0;
8210 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8211 {
8212 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8213 firsttile-=coldiff;
8214 lasttile+=coldiff;
8215 }
8216 for(int32_t t=firsttile; t<=lasttile; ++t)
8217 if(!rect_sel ||
8218 ((TILECOL(t)>=TILECOL(firsttile)) &&
8219 (TILECOL(t)<=TILECOL(lasttile))))
8220 reset_tile(newtilebuf, t, tf4Bit);
8221 saved=false;
8222 register_blank_tiles();
8223 }
8224
8225 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8226 {
8227 char buf[40];
8228
8229 if(tile==tile2)
8230 {
8231 sprintf(buf,"Delete tile %d?",tile);
8232 }
8233 else
8234 {
8235 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8236 }
8237
8238 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8239 {
8240 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8241
8242 go_tiles();
8243
8244 //if copying to an earlier tile, copy from left to right
8245 //otherwise, copy from right to left
8246 do_delete_tiles(firsttile, lasttile, rect_sel);
8247
8248 tile=tile2=zc_min(tile,tile2);
8249 saved=false;
8250 register_blank_tiles();
8251 }
8252 }
8253
8254 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8255 {
8256 byte buf[256];
8257 go_tiles();
8258
8259 unpack_tile(newtilebuf, dest, 0, false);
8260
8261 for(int32_t i=0; i<256; i++)
8262 buf[i] = unpackbuf[i];
8263
8264 unpack_tile(newtilebuf, src, 0, false);
8265
8266 if(newtilebuf[src].format>tf4Bit)
8267 {
8268 cs=0;
8269 }
8270
8271 cs &= 15;
8272 cs <<= CSET_SHFT;
8273
8274 for(int32_t i=0; i<256; i++)
8275 {
8276 if(backwards)
8277 {
8278 if(!buf[i])
8279 {
8280 buf[i] = unpackbuf[i]+cs;
8281 }
8282 }
8283 else
8284 {
8285 if(unpackbuf[i])
8286 {
8287 buf[i] = unpackbuf[i]+cs;
8288 }
8289 }
8290 }
8291
8292 pack_tile(newtilebuf, buf,dest);
8293 saved=false;
8294 }
8295
8296 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8297 {
8298 //byte buf[256];
8299 go_tiles();
8300
8301 if(!rect_sel)
8302 {
8303 for(int32_t d=dest1; d <= dest2; ++d)
8304 {
8305 /*unpack_tile(newtilebuf, d, 0, false);
8306
8307 for(int32_t i=0; i<256; i++)
8308 {
8309 if(!backwards)
8310 {
8311 if(!buf[i])
8312 {
8313 buf[i] = unpackbuf[i] + cs;
8314 }
8315 }
8316 else
8317 {
8318 if(unpackbuf[i])
8319 {
8320 buf[i] = unpackbuf[i] + cs;
8321 }
8322 }
8323 }
8324
8325 pack_tile(newtilebuf, buf,d);
8326 */
8327
8328 overlay_tile(newtilebuf,d,src,cs,backwards);
8329
8330 if(!blank_tile_table[src])
8331 {
8332 blank_tile_table[d]=false;
8333 }
8334 }
8335 }
8336 else
8337 {
8338 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8339 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8340 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8341 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8342 int32_t d=0;
8343
8344 for(int32_t j=cmin; j<=cmax; ++j)
8345 {
8346 for(int32_t k=rmin; k<=rmax; ++k)
8347 {
8348 d=j+TILES_PER_ROW*k;
8349 /*unpack_tile(newtilebuf, d, 0, false);
8350
8351 for(int32_t i=0; i<256; i++)
8352 {
8353 if(!backwards)
8354 {
8355 if(!buf[i])
8356 {
8357 buf[i] = unpackbuf[i] + cs;
8358 }
8359 }
8360 else
8361 {
8362 if(unpackbuf[i])
8363 {
8364 buf[i] = unpackbuf[i] + cs;
8365 }
8366 }
8367 }
8368
8369 pack_tile(newtilebuf, buf,d);
8370 */
8371
8372 overlay_tile(newtilebuf,d,src,cs,backwards);
8373
8374 if(!blank_tile_table[src])
8375 {
8376 blank_tile_table[d]=false;
8377 }
8378 }
8379 }
8380 }
8381
8382 return;
8383 }
8384
8385 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8386 {
8387 tile+=s;
8388 bound(tile,0,NEWMAXTILES-1);
8389
8390 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8391 tile2 = tile;
8392
8393 first = tile - (tile%TILES_PER_PAGE);
8394 }
8395
8396 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8397 {
8398 int32_t cst;
8399
8400 switch(bp2)
8401 {
8402 case tf4Bit:
8403 switch(newtilebuf[t].format)
8404 {
8405 case tf4Bit:
8406 //already in the right format
8407 break;
8408
8409 case tf8Bit:
8410 unpack_tile(newtilebuf, t, 0, true);
8411
8412 if(alt) //reduce
8413 {
8414 for(int32_t i=0; i<256; i++)
8415 {
8416 if(!shift||unpackbuf[i]!=0)
8417 {
8418 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8419 }
8420 }
8421 }
8422 else //truncate
8423 {
8424 for(int32_t i=0; i<256; i++)
8425 {
8426 unpackbuf[i]&=15;
8427 }
8428 }
8429
8430 reset_tile(newtilebuf, t, tf4Bit);
8431 pack_tile(newtilebuf, unpackbuf, t);
8432 break;
8433 }
8434
8435 break;
8436
8437 case tf8Bit:
8438 switch(newtilebuf[t].format)
8439 {
8440 case tf4Bit:
8441 unpack_tile(newtilebuf, t, 0, true);
8442 cst = cs&15;
8443 cst <<= CSET_SHFT;
8444
8445 for(int32_t i=0; i<256; i++)
8446 {
8447 if(!shift||unpackbuf[i]!=0)
8448 {
8449 unpackbuf[i]+=cst;
8450 }
8451 }
8452
8453 reset_tile(newtilebuf, t, tf8Bit);
8454 pack_tile(newtilebuf, unpackbuf, t);
8455 break;
8456
8457 case tf8Bit:
8458 //already in the right format
8459 break;
8460 }
8461
8462 break;
8463 }
8464 }
8465
8466 static DIALOG create_relational_tiles_dlg[] =
8467 {
8468 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8469 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8470 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8471 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8472 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8473 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8474 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8475 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8476 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8477 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8478 };
8479
8480 void draw_tile_list_window()
8481 {
8482 int32_t w = 640;
8483 int32_t h = 480;
8484
8485 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8486 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8487 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8488 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8489
8490 FONT *oldfont = font;
8491 font = get_zc_font(font_lfont);
8492 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8493 font=oldfont;
8494 return;
8495 }
8496
8497 void show_blank_tile(int32_t t)
8498 {
8499 char tbuf[80], tbuf2[80], tbuf3[80];
8500 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8501 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8502 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8503 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8504 }
8505
8506 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8507 {
8508 int num_bits;
8509 if (format == tf4Bit)
8510 num_bits = 4;
8511 else if (format == tf8Bit)
8512 num_bits = 8;
8513 else assert(false);
8514
8515 char buf[80];
8516 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8517
8518 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8519 {
8520 go_tiles();
8521 saved=false;
8522
8523 if(format == tf4Bit)
8524 {
8525 memset(cset_reduce_table, 0, 256);
8526 memset(col_diff,0,3*128);
8527 calc_cset_reduce_table(RAMpal, cs);
8528 }
8529
8530 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8531
8532 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8533 {
8534 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8535 firsttile-=coldiff;
8536 lasttile+=coldiff;
8537 }
8538
8539 for(int32_t t=firsttile; t<=lasttile; t++)
8540 if(!rect_sel ||
8541 ((TILECOL(t)>=TILECOL(firsttile)) &&
8542 (TILECOL(t)<=TILECOL(lasttile))))
8543 convert_tile(t, format, cs, shift, alt);
8544
8545 tile=tile2=zc_min(tile,tile2);
8546 }
8547 }
8548
8549
8550 int32_t readtilefile(PACKFILE *f)
8551 {
8552 dword section_version=0;
8553 dword section_cversion=0;
8554 int32_t zversion = 0;
8555 int32_t zbuild = 0;
8556
8557 if(!p_igetl(&zversion,f))
8558 {
8559 return 0;
8560 }
8561 if(!p_igetl(&zbuild,f))
8562 {
8563 return 0;
8564 }
8565 if(!p_igetw(&section_version,f))
8566 {
8567 return 0;
8568 }
8569 if(!p_igetw(&section_cversion,f))
8570 {
8571 return 0;
8572 }
8573 al_trace("readoneweapon section_version: %d\n", section_version);
8574 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8575
8576 if ( zversion > ZELDA_VERSION )
8577 {
8578 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8579 return 0;
8580 }
8581
8582 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8583 {
8584 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8585 return 0;
8586
8587 }
8588 else
8589 {
8590 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8591 }
8592
8593 int32_t index = 0;
8594 int32_t count = 0;
8595
8596 //tile id
8597 if(!p_igetl(&index,f))
8598 {
8599 return 0;
8600 }
8601 al_trace("Reading tile: index(%d)\n", index);
8602
8603 //tile count
8604 if(!p_igetl(&count,f))
8605 {
8606 return 0;
8607 }
8608 al_trace("Reading tile: count(%d)\n", count);
8609
8610
8611
8612
8613 for ( int32_t tilect = 0; tilect < count; tilect++ )
8614 {
8615 byte *temp_tile = new byte[tilesize(tf32Bit)];
8616 byte format=tf4Bit;
8617 memset(temp_tile, 0, tilesize(tf32Bit));
8618 if(!p_getc(&format,f))
8619 {
8620 delete[] temp_tile;
8621 return 0;
8622 }
8623
8624
8625 if(!pfread(temp_tile,tilesize(format),f))
8626 {
8627 delete[] temp_tile;
8628 return 0;
8629 }
8630
8631 reset_tile(newtilebuf, index+(tilect), format);
8632 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8633 delete[] temp_tile;
8634 }
8635
8636
8637 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8638
8639 register_blank_tiles();
8640 register_used_tiles();
8641
8642 return 1;
8643
8644 }
8645
8646 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8647 {
8648 dword section_version=0;
8649 dword section_cversion=0;
8650 int32_t zversion = 0;
8651 int32_t zbuild = 0;
8652
8653 if(!p_igetl(&zversion,f))
8654 {
8655 return 0;
8656 }
8657 if(!p_igetl(&zbuild,f))
8658 {
8659 return 0;
8660 }
8661 if(!p_igetw(&section_version,f))
8662 {
8663 return 0;
8664 }
8665 if(!p_igetw(&section_cversion,f))
8666 {
8667 return 0;
8668 }
8669 al_trace("readoneweapon section_version: %d\n", section_version);
8670 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8671
8672 if ( zversion > ZELDA_VERSION )
8673 {
8674 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8675 return 0;
8676 }
8677
8678 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8679 {
8680 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8681 return 0;
8682
8683 }
8684 else
8685 {
8686 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8687 }
8688
8689 int32_t index = 0;
8690 int32_t count = 0;
8691
8692 //tile id
8693 if(!p_igetl(&index,f))
8694 {
8695 return 0;
8696 }
8697 al_trace("Reading tile: index(%d)\n", index);
8698
8699 //tile count
8700 if(!p_igetl(&count,f))
8701 {
8702 return 0;
8703 }
8704 al_trace("Reading tile: count(%d)\n", count);
8705
8706
8707 for ( int32_t tilect = 0; tilect < count; tilect++ )
8708 {
8709 byte *temp_tile = new byte[tilesize(tf32Bit)];
8710 byte format=tf4Bit;
8711 memset(temp_tile, 0, tilesize(tf32Bit));
8712 if(!p_getc(&format,f))
8713 {
8714 delete[] temp_tile;
8715 return 0;
8716 }
8717
8718
8719 if(!pfread(temp_tile,tilesize(format),f))
8720 {
8721 delete[] temp_tile;
8722 return 0;
8723 }
8724
8725 reset_tile(newtilebuf, start+(tilect), format);
8726 if ( skip )
8727 {
8728 if ( (start+(tilect)) < skip )
8729 {
8730 delete[] temp_tile;
8731 continue;
8732 }
8733
8734 }
8735 if ( start+(tilect) < NEWMAXTILES )
8736 {
8737 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8738 }
8739 delete[] temp_tile;
8740
8741 }
8742
8743
8744 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8745
8746 register_blank_tiles();
8747 register_used_tiles();
8748
8749 return 1;
8750
8751 }
8752
8753
8754 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8755 {
8756 dword section_version=0;
8757 dword section_cversion=0;
8758 int32_t zversion = 0;
8759 int32_t zbuild = 0;
8760
8761 if(!p_igetl(&zversion,f))
8762 {
8763 return 0;
8764 }
8765 if(!p_igetl(&zbuild,f))
8766 {
8767 return 0;
8768 }
8769 if(!p_igetw(&section_version,f))
8770 {
8771 return 0;
8772 }
8773 if(!p_igetw(&section_cversion,f))
8774 {
8775 return 0;
8776 }
8777 al_trace("readoneweapon section_version: %d\n", section_version);
8778 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8779
8780 if ( zversion > ZELDA_VERSION )
8781 {
8782 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8783 return 0;
8784 }
8785
8786 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8787 {
8788 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8789 return 0;
8790
8791 }
8792 else
8793 {
8794 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8795 }
8796
8797 int32_t index = 0;
8798 int32_t count = 0;
8799
8800 //tile id
8801 if(!p_igetl(&index,f))
8802 {
8803 return 0;
8804 }
8805 al_trace("Reading tile: index(%d)\n", index);
8806
8807 //tile count
8808 if(!p_igetl(&count,f))
8809 {
8810 return 0;
8811 }
8812 al_trace("Reading tile: count(%d)\n", count);
8813
8814
8815
8816
8817 for ( int32_t tilect = 0; tilect < count; tilect++ )
8818 {
8819 byte *temp_tile = new byte[tilesize(tf32Bit)];
8820 byte format=tf4Bit;
8821 memset(temp_tile, 0, tilesize(tf32Bit));
8822
8823 if(!p_getc(&format,f))
8824 {
8825 delete[] temp_tile;
8826 return 0;
8827 }
8828
8829
8830 if(!pfread(temp_tile,tilesize(format),f))
8831 {
8832 delete[] temp_tile;
8833 return 0;
8834 }
8835
8836 reset_tile(newtilebuf, start+(tilect), format);
8837 if ( start+(tilect) < NEWMAXTILES )
8838 {
8839 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8840 }
8841 delete[] temp_tile;
8842 }
8843
8844
8845 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8846
8847 register_blank_tiles();
8848 register_used_tiles();
8849
8850 return 1;
8851
8852 }
8853 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8854 {
8855 dword section_version=V_TILES;
8856 dword section_cversion=CV_TILES;
8857 int32_t zversion = ZELDA_VERSION;
8858 int32_t zbuild = VERSION_BUILD;
8859
8860 if(!p_iputl(zversion,f))
8861 {
8862 return 0;
8863 }
8864 if(!p_iputl(zbuild,f))
8865 {
8866 return 0;
8867 }
8868 if(!p_iputw(section_version,f))
8869 {
8870 return 0;
8871 }
8872
8873 if(!p_iputw(section_cversion,f))
8874 {
8875 return 0;
8876 }
8877
8878 //start tile id
8879 if(!p_iputl(index,f))
8880 {
8881 return 0;
8882 }
8883
8884 //count
8885 if(!p_iputl(count,f))
8886 {
8887 return 0;
8888 }
8889
8890 for ( int32_t tilect = 0; tilect < count; tilect++ )
8891 {
8892 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8893 {
8894 return 0;
8895 }
8896 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8897 {
8898 return 0;
8899 }
8900 }
8901
8902 return 1;
8903
8904 }
8905
8906 static int32_t _selected_tile=-1, _selected_tcset=-1;
8907 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8908 {
8909 popup_zqdialog_start();
8910 reset_combo_animations();
8911 reset_combo_animations2();
8912 bound(tile,0,NEWMAXTILES-1);
8913 ex=exnow;
8914 int32_t done=0;
8915 int32_t oflip=flip;
8916 int32_t otile=tile;
8917 int32_t ocs=cs;
8918 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8919 int32_t copy=-1;
8920 int32_t tile2=tile,copycnt=0;
8921 int32_t tile_clicked=-1;
8922 bool rect_sel=true;
8923 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8924 position_mouse_z(0);
8925
8926 go();
8927
8928 register_used_tiles();
8929 int32_t w = 640;
8930 int32_t h = 480;
8931 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8932 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8933 int32_t screen_xofs=window_xofs+6;
8934 int32_t screen_yofs=window_yofs+25;
8935 int32_t panel_yofs=3;
8936 int32_t mul = 2;
8937 FONT *tfont = get_zc_font(font_lfont_l);
8938
8939 draw_tile_list_window();
8940 int32_t f=0;
8941 draw_tiles(first,cs,f);
8942
8943 if(type==0)
8944 {
8945 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
8946 }
8947 else
8948 {
8949 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
8950 }
8951
8952 go_tiles();
8953
8954 while(gui_mouse_b())
8955 {
8956 /* do nothing */
8957 rest(1);
8958 }
8959
8960 bool bdown=false;
8961
8962 #define FOREACH_START(_t) \
8963 { \
8964 int32_t _first, _last; \
8965 if(is_rect) \
8966 { \
8967 _first=top*TILES_PER_ROW+left; \
8968 _last=_first+rows*TILES_PER_ROW|+columns-1; \
8969 } \
8970 else \
8971 { \
8972 _first=zc_min(tile, tile2); \
8973 _last=zc_max(tile, tile2); \
8974 } \
8975 for(int32_t _t=_first; _t<=_last; _t++) \
8976 { \
8977 if(is_rect) \
8978 { \
8979 int32_t row=TILEROW(_t); \
8980 if(row<top || row>=top+rows) \
8981 continue; \
8982 int32_t col=TILECOL(_t); \
8983 if(col<left || col>=left+columns) \
8984 continue; \
8985 } \
8986
8987 #define FOREACH_END\
8988 } \
8989 }
8990
8991 bool did_snap = false;
8992 int otl = tile, otl2 = tile2;
8993 do
8994 {
8995 HANDLE_CLOSE_ZQDLG();
8996 if(exiting_program) break;
8997 rest(4);
8998 int32_t top=TILEROW(zc_min(tile, tile2));
8999 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9000 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9001 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9002 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9003 bool redraw=false;
9004
9005 if(mouse_z!=0)
9006 {
9007 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9008 position_mouse_z(0);
9009 redraw=true;
9010 }
9011
9012 if(keypressed())
9013 {
9014 switch(readkey()>>8)
9015 {
9016 case KEY_ENTER_PAD:
9017 case KEY_ENTER:
9018 done=2;
9019 break;
9020
9021 case KEY_ESC:
9022 done=1;
9023 break;
9024
9025 case KEY_F1:
9026 onHelp();
9027 break;
9028
9029 case KEY_EQUALS:
9030 case KEY_PLUS_PAD:
9031 {
9032 if(CHECK_CTRL_CMD ||
9033 key[KEY_ALT] || key[KEY_ALTGR])
9034 {
9035 FOREACH_START(t)
9036 if(key[KEY_ALT] || key[KEY_ALTGR])
9037 shift_tile_colors(t, 16, false);
9038 else
9039 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9040 FOREACH_END
9041
9042 register_blank_tiles();
9043 }
9044 else if(edit_cs)
9045 cs = (cs<13) ? cs+1:0;
9046
9047 redraw=true;
9048 break;
9049 }
9050
9051 case KEY_Z:
9052 case KEY_F12:
9053 {
9054 if(!did_snap)
9055 {
9056 //Export tile page as screenshot
9057 PALETTE temppal;
9058 get_palette(temppal);
9059 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9060 draw_tiles(tempbmp,first,cs,f,false,true);
9061 save_bitmap(getSnapName(), tempbmp, RAMpal);
9062 destroy_bitmap(tempbmp);
9063
9064 redraw = true;
9065 did_snap = true;
9066 }
9067 break;
9068 }
9069
9070 case KEY_S:
9071 {
9072 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9073 break;
9074 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9075 if(!f) break;
9076 al_trace("Saving tile: %d\n", tile);
9077 writetilefile(f,tile,1);
9078 pack_fclose(f);
9079 break;
9080 }
9081 case KEY_L:
9082 {
9083 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9084 break;
9085 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9086 if(!f) break;
9087 al_trace("Saving tile: %d\n", tile);
9088 if (!readtilefile(f))
9089 {
9090 al_trace("Could not read from .ztile packfile %s\n", temppath);
9091 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9092 }
9093 else
9094 {
9095 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9096 }
9097
9098 pack_fclose(f);
9099 //register_blank_tiles();
9100 //register_used_tiles();
9101 redraw=true;
9102 break;
9103 }
9104 case KEY_MINUS:
9105 case KEY_MINUS_PAD:
9106 {
9107 if(CHECK_CTRL_CMD ||
9108 key[KEY_ALT] || key[KEY_ALTGR])
9109 {
9110 FOREACH_START(t)
9111 if(key[KEY_ALT] || key[KEY_ALTGR])
9112 shift_tile_colors(t, -16, false);
9113 else
9114 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9115 FOREACH_END
9116
9117 register_blank_tiles();
9118 }
9119 else if(edit_cs)
9120 cs = (cs>0) ? cs-1:13;
9121
9122 redraw=true;
9123 break;
9124 }
9125
9126 case KEY_UP:
9127 {
9128 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9129 {
9130 case 3: //ALT and CTRL
9131 case 2: //ALT
9132 if(is_rect)
9133 {
9134 saved=false;
9135 go_slide_tiles(columns, rows, top, left);
9136 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9137 bool same = true;
9138
9139 for(int32_t d=0; d<columns; d++)
9140 {
9141 for(int32_t s=0; s<rows; s++)
9142 {
9143 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9144
9145 if(newtilebuf[t].format!=bitcheck) same = false;
9146 }
9147 }
9148
9149 if(!same) break;
9150
9151 // This used to do something. Too lazy to remove.
9152 // Can probably remove the above "same" check too.
9153 bitcheck = 2;
9154
9155 for(int32_t c=0; c<columns; c++)
9156 {
9157 for(int32_t r=0; r<rows; r++)
9158 {
9159 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9160 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9161 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9162
9163 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9164 {
9165 if(pixelrow==15*bitcheck)
9166 {
9167 int32_t srctile=temptile+TILES_PER_ROW;
9168 if(srctile>=NEWMAXTILES)
9169 srctile-=rows*TILES_PER_ROW;
9170 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9171 }
9172
9173 *dest_pixelrow=*src_pixelrow;
9174 dest_pixelrow++;
9175 src_pixelrow++;
9176 }
9177 }
9178
9179 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9180
9181 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9182 {
9183 if((CHECK_CTRL_CMD))
9184 {
9185 *dest_pixelrow=0;
9186 }
9187 else
9188 {
9189 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9190 *dest_pixelrow=*src_pixelrow;
9191 }
9192 }
9193 }
9194 }
9195
9196 register_blank_tiles();
9197 redraw=true;
9198 break;
9199
9200 case 1: //CTRL
9201 case 0: //None
9202 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9203 redraw=true;
9204
9205 default: //Others
9206 break;
9207 }
9208 }
9209 break;
9210
9211 case KEY_DOWN:
9212 {
9213 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9214 {
9215 case 3: //ALT and CTRL
9216 case 2: //ALT
9217 if(is_rect)
9218 {
9219 saved=false;
9220 go_slide_tiles(columns, rows, top, left);
9221 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9222 bool same = true;
9223
9224 for(int32_t c=0; c<columns; c++)
9225 {
9226 for(int32_t r=0; r<rows; r++)
9227 {
9228 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9229
9230 if(newtilebuf[t].format!=bitcheck) same = false;
9231 }
9232 }
9233
9234 if(!same) break;
9235
9236 // This used to do something. Too lazy to remove.
9237 // Can probably remove the above "same" check too.
9238 bitcheck = 2;
9239
9240 for(int32_t c=0; c<columns; c++)
9241 {
9242 for(int32_t r=rows-1; r>=0; r--)
9243 {
9244 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9245 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9246 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9247
9248 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9249 {
9250 if(pixelrow<bitcheck)
9251 {
9252 int32_t srctile=temptile-TILES_PER_ROW;
9253 if(srctile<0)
9254 srctile+=rows*TILES_PER_ROW;
9255 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9256 *dest_pixelrow=*tempsrc;
9257 //*dest_pixelrow=0;
9258 }
9259 else
9260 {
9261 *dest_pixelrow=*src_pixelrow;
9262 }
9263
9264 dest_pixelrow--;
9265 src_pixelrow--;
9266 }
9267 }
9268
9269 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9270 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9271
9272 for(int32_t b=0; b<bitcheck; b++)
9273 {
9274 if((CHECK_CTRL_CMD))
9275 {
9276 *dest_pixelrow=0;
9277 }
9278 else
9279 {
9280 *dest_pixelrow=*src_pixelrow;
9281 }
9282
9283 dest_pixelrow++;
9284 src_pixelrow++;
9285 }
9286 }
9287 }
9288
9289 register_blank_tiles();
9290 redraw=true;
9291 break;
9292
9293 case 1: //CTRL
9294 case 0: //None
9295 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9296 redraw=true;
9297
9298 default: //Others
9299 break;
9300 }
9301 }
9302 break;
9303
9304 case KEY_LEFT:
9305 {
9306 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9307 {
9308 case 3: //ALT and CTRL
9309 case 2: //ALT
9310 if(is_rect)
9311 {
9312 saved=false;
9313 go_slide_tiles(columns, rows, top, left);
9314 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9315 bool same = true;
9316
9317 for(int32_t c=0; c<columns; c++)
9318 {
9319 for(int32_t r=0; r<rows; r++)
9320 {
9321 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9322
9323 if(newtilebuf[t].format!=bitcheck) same = false;
9324 }
9325 }
9326
9327 if(!same) break;
9328
9329 // This used to do something. Too lazy to remove.
9330 // Can probably remove the above "same" check too.
9331 bitcheck = 2;
9332
9333 for(int32_t r=0; r<rows; r++)
9334 {
9335 for(int32_t c=0; c<columns; c++)
9336 {
9337 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9338 byte *dest_pixelrow=(newtilebuf[temptile].data);
9339
9340 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9341 {
9342 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9343 {
9344 *dest_pixelrow=*(dest_pixelrow+1);
9345 dest_pixelrow++;
9346 }
9347
9348 if(c==columns-1)
9349 {
9350 if(!(CHECK_CTRL_CMD))
9351 {
9352 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9353 *dest_pixelrow=*tempsrc;
9354 }
9355 }
9356 else
9357
9358 {
9359 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9360 *dest_pixelrow=*tempsrc;
9361 }
9362
9363 dest_pixelrow++;
9364 }
9365 }
9366 }
9367
9368 register_blank_tiles();
9369 redraw=true;
9370 }
9371
9372 break;
9373
9374 case 1: //CTRL
9375 case 0: //None
9376 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9377 redraw=true;
9378
9379 default: //Others
9380 break;
9381 }
9382 }
9383 break;
9384
9385 case KEY_RIGHT:
9386 {
9387 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9388 {
9389 case 3: //ALT and CTRL
9390 case 2: //ALT
9391 if(is_rect)
9392 {
9393 saved=false;
9394 go_slide_tiles(columns, rows, top, left);
9395 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9396 bool same = true;
9397
9398 for(int32_t c=0; c<columns; c++)
9399 {
9400 for(int32_t r=0; r<rows; r++)
9401 {
9402 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9403
9404 if(newtilebuf[t].format!=bitcheck) same = false;
9405 }
9406 }
9407
9408 if(!same) break;
9409
9410 // This used to do something. Too lazy to remove.
9411 // Can probably remove the above "same" check too.
9412 bitcheck = 2;
9413
9414 for(int32_t r=0; r<rows; r++)
9415 {
9416 for(int32_t c=columns-1; c>=0; c--)
9417 {
9418 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9419 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9420
9421 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9422 {
9423 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9424 {
9425 *dest_pixelrow=*(dest_pixelrow-1);
9426 dest_pixelrow--;
9427 }
9428
9429 if(c==0)
9430 {
9431 if(!(CHECK_CTRL_CMD))
9432 {
9433 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9434 *dest_pixelrow=*tempsrc;
9435 }
9436 }
9437 else
9438 {
9439 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9440 *dest_pixelrow=*tempsrc;
9441 }
9442
9443 dest_pixelrow--;
9444 }
9445 }
9446 }
9447
9448 register_blank_tiles();
9449 redraw=true;
9450 }
9451
9452 break;
9453
9454 case 1: //CTRL
9455 case 0: //None
9456 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9457 redraw=true;
9458
9459 default: //Others
9460 break;
9461 }
9462 }
9463 break;
9464
9465 case KEY_PGUP:
9466 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9467 redraw=true;
9468 break;
9469
9470 case KEY_PGDN:
9471 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9472 redraw=true;
9473 break;
9474
9475 case KEY_HOME:
9476 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9477 redraw=true;
9478 break;
9479
9480 case KEY_END:
9481 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9482 redraw=true;
9483 break;
9484
9485 case KEY_P:
9486 {
9487 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9488
9489 if(whatPage >= 0)
9490 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9491
9492 break;
9493 }
9494
9495 case KEY_O:
9496 if(type==0 && copy>=0)
9497 {
9498 go_tiles();
9499
9500 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9501 {
9502 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9503 saved=false;
9504 }
9505 else
9506 {
9507 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9508 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9509 }
9510
9511 saved=false;
9512 redraw=true;
9513 }
9514
9515 break;
9516
9517 case KEY_E:
9518 if(type==0)
9519 {
9520 edit_tile(tile,flip,cs);
9521 draw_tile_list_window();
9522 redraw=true;
9523 }
9524
9525 break;
9526
9527 case KEY_G:
9528 if(type==0)
9529 {
9530 grab_tile(tile,cs);
9531 draw_tile_list_window();
9532 redraw=true;
9533 }
9534
9535 break;
9536
9537 case KEY_C:
9538 copy=zc_min(tile,tile2);
9539 copycnt=abs(tile-tile2)+1;
9540 redraw=true;
9541 break;
9542
9543 case KEY_X:
9544 if(type==2)
9545 {
9546 ex=(ex+1)%3;
9547 }
9548
9549 break;
9550
9551 //usetiles=true;
9552 case KEY_R:
9553 if(type==2)
9554 break;
9555 if(type==1)
9556 {
9557 flip = rotate_value(flip);
9558 redraw=true;
9559 break;
9560 }
9561
9562 go_tiles();
9563
9564 if(CHECK_CTRL_CMD)
9565 {
9566 bool go=false;
9567 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9568 go=true;
9569 else if(massRecolorSetup(cs))
9570 go=true;
9571
9572 if(go)
9573 {
9574 FOREACH_START(t)
9575 massRecolorApply(t);
9576 FOREACH_END
9577
9578 register_blank_tiles();
9579 }
9580 }
9581 else
9582 {
9583 FOREACH_START(t)
9584 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9585 FOREACH_END
9586 }
9587
9588 redraw=true;
9589 saved=false;
9590 break;
9591
9592 case KEY_SPACE:
9593 rect_sel=!rect_sel;
9594 copy=-1;
9595 redraw=true;
9596 break;
9597
9598 // case KEY_N: go_tiles(); normalize(tile,tile2,flip); flip=0; redraw=true; saved=false; usetiles=true; break;
9599 case KEY_H:
9600 flip^=1;
9601 go_tiles();
9602
9603 if(type==0)
9604 {
9605 normalize(tile,tile2,rect_sel,flip);
9606 flip=0;
9607 }
9608
9609 redraw=true;
9610 break;
9611
9612
9613 case KEY_V:
9614 if(copy==-1)
9615 {
9616 if(type!=2)
9617 {
9618 flip^=2;
9619 go_tiles();
9620
9621 if(type==0)
9622 {
9623 normalize(tile,tile2,rect_sel,flip);
9624 flip=0;
9625 }
9626 }
9627 }
9628 else
9629 {
9630 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9631 go_tiles();
9632 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9633 }
9634
9635 redraw=true;
9636 break;
9637
9638 case KEY_F:
9639 if(copy==-1)
9640 {
9641 break;
9642 }
9643 else
9644 {
9645 go_tiles();
9646 {
9647 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9648 }
9649 }
9650
9651 redraw=true;
9652 break;
9653
9654 case KEY_DEL:
9655 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9656 {
9657 bool warn = (rect_sel
9658 && ((tile/20)!=(tile2/20))
9659 && !(tile%20==0&&tile2%20==19));
9660 int32_t z=zc_min(tile,tile2);
9661 int32_t count = abs(tile-tile2) + 1;
9662 tile=z;
9663 tile2=NEWMAXTILES;
9664 copy = tile + count;
9665 copycnt = NEWMAXTILES-copy;
9666 char buf[64];
9667
9668 if(count>1)
9669 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9670 else
9671 sprintf(buf,"Remove tile %d?",tile);
9672
9673 AlertDialog("Remove Tiles", std::string(buf)
9674 +"\nThis will offset the tiles that follow!"
9675 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9676 [&](bool ret,bool)
9677 {
9678 if(ret)
9679 {
9680 go_tiles();
9681 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9682 {
9683 redraw=true;
9684 saved=false;
9685 }
9686 }
9687 }).show();
9688 }
9689 delete_tiles(tile,tile2,rect_sel);
9690 redraw=true;
9691 break;
9692
9693 case KEY_U:
9694 {
9695 if(CHECK_CTRL_CMD)
9696 {
9697 //Only toggle the first 2 bits!
9698 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9699 }
9700 else
9701 {
9702 comeback_tiles();
9703 }
9704
9705 redraw=true;
9706 }
9707 break;
9708
9709 case KEY_8:
9710 case KEY_8_PAD:
9711 hide_8bit_marker();
9712 break;
9713
9714 case KEY_I: //insert tiles
9715 if(type==0)
9716 {
9717 bool warn = (rect_sel
9718 && ((tile/20)!=(tile2/20))
9719 && !(tile%20==0&&tile2%20==19));
9720 int32_t z=zc_min(tile,tile2);
9721 int32_t count = abs(tile-tile2) + 1;
9722 tile=z;
9723 tile2=NEWMAXTILES;
9724 copy = tile + count;
9725 copycnt = NEWMAXTILES-copy;
9726
9727 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9728 {
9729 char buf[64];
9730
9731 if(count>1)
9732 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9733 else
9734 sprintf(buf,"Remove tile %d?",tile);
9735
9736 AlertDialog("Remove Tiles", std::string(buf)
9737 +"\nThis will offset the tiles that follow!"
9738 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9739 [&](bool ret,bool)
9740 {
9741 if(ret)
9742 {
9743 go_tiles();
9744 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9745 {
9746 redraw=true;
9747 saved=false;
9748 }
9749 }
9750 }).show();
9751 }
9752 else
9753 {
9754 char buf[64];
9755
9756 if(count>1)
9757 sprintf(buf,"Insert %d blank tiles?",count);
9758 else
9759 sprintf(buf,"Insert a blank tile?");
9760
9761 AlertDialog("Insert Tiles", std::string(buf)
9762 +"\nThis will offset the tiles that follow!"
9763 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9764 [&](bool ret,bool)
9765 {
9766 if(ret)
9767 {
9768 go_tiles();
9769 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9770 {
9771 redraw=true;
9772 saved=false;
9773 }
9774 }
9775 }).show();
9776 }
9777
9778 copy=-1;
9779 tile2=tile=z;
9780 }
9781 break;
9782 case KEY_M:
9783 if(type==0)
9784 {
9785 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9786 {
9787 go_tiles();
9788 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9789 saved=false;
9790 }
9791 else if(copy==-1)
9792 {
9793 // I don't know what this was supposed to be doing before.
9794 // It didn't work in anything like a sensible way.
9795 if(rect_sel)
9796 {
9797 make_combos_rect(top, left, rows, columns, cs);
9798 }
9799 else
9800 {
9801 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9802 }
9803 }
9804
9805 redraw=true;
9806 }
9807 break;
9808
9809 case KEY_D:
9810 {
9811 int32_t frames=1;
9812 char buf[80];
9813 sprintf(buf, "%d", frames);
9814 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9815 create_relational_tiles_dlg[2].dp=buf;
9816
9817 large_dialog(create_relational_tiles_dlg);
9818
9819 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9820
9821 if(ret==5)
9822 {
9823 frames=zc_max(atoi(buf),1);
9824 bool same = true;
9825 int32_t bitcheck=newtilebuf[tile].format;
9826
9827 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9828 {
9829 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9830 }
9831
9832 if(!same)
9833 {
9834 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9835 break;
9836 }
9837
9838 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9839 {
9840 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9841 break;
9842 }
9843
9844 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9845 {
9846 reset_tile(newtilebuf, tile+i, bitcheck);
9847 }
9848
9849 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9850 {
9851 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9852 {
9853 for(int32_t j=0; j<frames; ++j)
9854 {
9855 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9856 }
9857 }
9858 }
9859 else
9860 {
9861 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9862 {
9863 for(int32_t j=0; j<frames; ++j)
9864 {
9865 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9866 }
9867 }
9868 }
9869 }
9870 register_blank_tiles();
9871 register_used_tiles();
9872 redraw=true;
9873 saved=false;
9874 break;
9875 }
9876
9877 case KEY_B:
9878 {
9879 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9880 bool control=(CHECK_CTRL_CMD);
9881 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9882 int format = control ? tf4Bit : tf8Bit;
9883
9884 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9885 register_blank_tiles();
9886 }
9887 break;
9888 }
9889
9890 clear_keybuf();
9891 }
9892
9893 if(!(key[KEY_Z] || key[KEY_F12]))
9894 did_snap = false;
9895
9896 if(gui_mouse_b()&1)
9897 {
9898 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9899 {
9900 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9901 {
9902 done=1;
9903 }
9904 }
9905
9906 int32_t x=gui_mouse_x()-screen_xofs;
9907 int32_t y=gui_mouse_y()-screen_yofs;
9908
9909 if(y>=0 && y<208*mul)
9910 {
9911 x=zc_min(zc_max(x,0),(320*mul)-1);
9912 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9913
9914 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9915 {
9916 tile2=t;
9917 }
9918 else
9919 {
9920 tile=tile2=t;
9921 }
9922
9923 if(tile_clicked!=t)
9924 {
9925 dclick_status=DCLICK_NOT;
9926 }
9927 else if(dclick_status == DCLICK_AGAIN)
9928 {
9929 while(gui_mouse_b())
9930 {
9931 /* do nothing */
9932 rest(1);
9933 }
9934
9935 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
9936 {
9937 dclick_status=DCLICK_NOT;
9938 }
9939 else
9940 {
9941 if(type==0)
9942 {
9943 edit_tile(tile,flip,cs);
9944 draw_tile_list_window();
9945 redraw=true;
9946 }
9947 else
9948 {
9949 done=2;
9950 }
9951 }
9952 }
9953
9954 tile_clicked=t;
9955 }
9956 else if(x>300*mul && !bdown)
9957 {
9958 if(y<224*mul && first>0)
9959 {
9960 first-=TILES_PER_PAGE;
9961 redraw=true;
9962 }
9963
9964 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
9965 {
9966 first+=TILES_PER_PAGE;
9967 redraw=true;
9968 }
9969
9970 bdown=true;
9971 }
9972
9973 if(type==1||type==2)
9974 {
9975 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
9976 done=1;
9977
9978 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
9979 done=2;
9980 }
9981 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
9982 {
9983 rect_sel=!rect_sel;
9984 copy=-1;
9985 redraw=true;
9986 }
9987 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
9988 {
9989 FONT *tf = font;
9990 font = tfont;
9991
9992 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
9993 {
9994 font = tf;
9995 grab_tile(tile,cs);
9996 draw_tile_list_window();
9997 position_mouse_z(0);
9998 redraw=true;
9999 }
10000
10001 font = tf;
10002 }
10003 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10004 {
10005 FONT *tf = font;
10006 font = tfont;
10007
10008 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10009 {
10010 font = tf;
10011 edit_tile(tile,flip,cs);
10012 draw_tile_list_window();
10013 redraw=true;
10014 }
10015
10016 font = tf;
10017 }
10018 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10019 {
10020 FONT *tf = font;
10021 font = tfont;
10022
10023 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10024 {
10025 strcpy(datapath, "tileset.png");
10026 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,datapath,true))
10027 {
10028 PALETTE temppal;
10029 get_palette(temppal);
10030 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10031 draw_tiles(tempbmp,first,cs,f,false,true);
10032 save_bitmap(temppath, tempbmp, RAMpal);
10033 destroy_bitmap(tempbmp);
10034 }
10035 }
10036
10037 font = tf;
10038 }
10039 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10040 {
10041 FONT *tf = font;
10042 font = tfont;
10043
10044 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10045 {
10046 if(massRecolorSetup(cs))
10047 {
10048 go_tiles();
10049
10050 FOREACH_START(t)
10051 massRecolorApply(t);
10052 FOREACH_END
10053
10054 register_blank_tiles();
10055 }
10056 }
10057
10058 font = tf;
10059 }
10060 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10061 {
10062 FONT *tf = font;
10063 font = tfont;
10064
10065 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10066 {
10067 done=1;
10068 }
10069
10070 font = tf;
10071 }
10072
10073 bdown=true;
10074 }
10075
10076 bool r_click = false;
10077
10078 if(gui_mouse_b()&2 && !bdown && type==0)
10079 {
10080 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10081 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10082
10083 if(y>=0 && y<208*mul)
10084 {
10085 x=zc_min(zc_max(x,0),(320*mul)-1);
10086 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10087
10088 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10089 tile=tile2=t;
10090 }
10091
10092 bdown = r_click = true;
10093 f=8;
10094 }
10095
10096 if(gui_mouse_b()==0)
10097 bdown=false;
10098
10099 position_mouse_z(0);
10100
10101 REDRAW:
10102
10103 if((f%8)==0 || InvalidBG == 1)
10104 redraw=true;
10105 if(otl != tile || otl2 != tile2)
10106 {
10107 otl = tile;
10108 otl2 = tile2;
10109 redraw = true;
10110 }
10111
10112 if(redraw)
10113 {
10114 draw_tiles(first,cs,f);
10115 }
10116 if(f&8)
10117 {
10118 if(rect_sel)
10119 {
10120 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10121 zc_min(TILECOL(tile),TILECOL(tile2));
10122 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10123 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10124 {
10125 if(i>=first && i<first+TILES_PER_PAGE &&
10126 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10127 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10128 {
10129 int32_t x=TILECOL(i)<<(5);
10130 int32_t y=TILEROW(i-first)<<(5);
10131 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10132 }
10133 }
10134 }
10135 else
10136 {
10137 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10138 {
10139 if(i>=first && i<first+TILES_PER_PAGE)
10140 {
10141 int32_t x=TILECOL(i)<<(5);
10142 int32_t y=TILEROW(i-first)<<(5);
10143 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10144 }
10145 }
10146 }
10147 }
10148
10149 if(type==0)
10150 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10151 else
10152 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10153
10154 if(type==2)
10155 {
10156 char cbuf[16];
10157 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10158 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10159 }
10160
10161 ++f;
10162
10163 if(r_click)
10164 {
10165 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10166 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10167 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10168 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10169
10170 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10171 if (newtilebuf[tile].format == tf8Bit)
10172 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10173 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10174 select_tile_color_depth_cb = [&](int format){
10175 if (newtilebuf[tile].format == format)
10176 return;
10177
10178 bool skip_prompt = true;
10179 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10180 };
10181
10182 NewMenu rcmenu
10183 {
10184 { "Copy", [&]()
10185 {
10186 copy = zc_min(tile,tile2);
10187 copycnt = abs(tile-tile2)+1;
10188 } },
10189 { "Paste", [&]()
10190 {
10191 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10192 if(saved) saved = !b;
10193 }, nullopt, copy < 0 },
10194 { "Move", [&]()
10195 {
10196 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10197 if(saved) saved = !b;
10198 }, nullopt, copy < 0 },
10199 { "Clear", [&]()
10200 {
10201 delete_tiles(tile, tile2, rect_sel);
10202 } },
10203 {},
10204 { "Edit", [&]()
10205 {
10206 edit_tile(tile, flip, cs);
10207 draw_tile_list_window();
10208 } },
10209 { "Grab", [&]()
10210 {
10211 grab_tile(tile, cs);
10212 draw_tile_list_window();
10213 position_mouse_z(0);
10214 } },
10215 { "Scale", [&]()
10216 {
10217 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10218 if(saved) saved = !b;
10219 }, nullopt, type != 0 },
10220 { "Angular Rotation", [&]()
10221 {
10222 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10223 if(saved) saved = !b;
10224 }, nullopt, type != 0 },
10225 { "Color Depth", &select_tile_color_depth_menu },
10226 {},
10227 { "Blank?", [&]()
10228 {
10229 show_blank_tile(tile);
10230 } },
10231 {},
10232 { "View ", &select_tile_view_menu },
10233 { "Overlay", [&]()
10234 {
10235 overlay_tile(newtilebuf, tile, copy, cs, 0);
10236 } },
10237 { "H-Flip", [&]()
10238 {
10239 flip ^= 1;
10240 go_tiles();
10241
10242 if(type == 0)
10243 {
10244 normalize(tile, tile2, rect_sel, flip);
10245 flip = 0;
10246 }
10247 } },
10248 { "V-Flip", [&]()
10249 {
10250 flip ^= 2;
10251 go_tiles();
10252
10253 if(type == 0)
10254 {
10255 normalize(tile, tile2, rect_sel, flip);
10256 flip = 0;
10257 }
10258 } },
10259 { "Create Combos", [&]()
10260 {
10261 if(rect_sel)
10262 make_combos_rect(top, left, rows, columns, cs);
10263 else
10264 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10265 }, nullopt, type != 0 },
10266 { "Insert", [&]()
10267 {
10268 bool warn = (rect_sel
10269 && ((tile/20)!=(tile2/20))
10270 && !(tile%20==0&&tile2%20==19));
10271 int32_t z = zc_min(tile, tile2);
10272 int32_t count = abs(tile-tile2) + 1;
10273 tile = z;
10274 tile2 = NEWMAXTILES;
10275 copy = tile + count;
10276 copycnt = NEWMAXTILES-copy;
10277
10278 string msg;
10279
10280 if(count>1)
10281 msg = fmt::format("Insert {} blank tiles?",count);
10282 else
10283 msg = "Insert a blank tile?";
10284
10285 AlertDialog("Insert Tiles", msg
10286 +"\nThis will offset the tiles that follow!"
10287 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10288 [&](bool ret,bool)
10289 {
10290 if(ret)
10291 {
10292 go_tiles();
10293 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10294 saved = false;
10295 }
10296 }).show();
10297
10298 copy=-1;
10299 tile2=tile=z;
10300 }, nullopt, type != 0 },
10301 { "Remove", [&]()
10302 {
10303 bool warn = (rect_sel
10304 && ((tile/20)!=(tile2/20))
10305 && !(tile%20==0&&tile2%20==19));
10306 int32_t z = zc_min(tile, tile2);
10307 int32_t count = abs(tile-tile2) + 1;
10308 tile = z;
10309 tile2 = NEWMAXTILES;
10310 copy = tile + count;
10311 copycnt = NEWMAXTILES-copy;
10312
10313 string msg;
10314
10315 if(count>1)
10316 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10317 else
10318 msg = fmt::format("Remove tile {}?", tile);
10319
10320 AlertDialog("Remove Tiles", msg
10321 +"\nThis will offset the tiles that follow!"
10322 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10323 [&](bool ret,bool)
10324 {
10325 if(ret)
10326 {
10327 go_tiles();
10328 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10329 saved = false;
10330 }
10331 }).show();
10332
10333 copy=-1;
10334 tile2=tile=z;
10335 }, nullopt, type != 0 },
10336 };
10337 rcmenu.pop(window_mouse_x(),window_mouse_y());
10338 redraw = true;
10339 r_click = false;
10340 goto REDRAW;
10341 }
10342 update_hw_screen();
10343 }
10344 while(!done);
10345
10346 while(gui_mouse_b())
10347 {
10348 /* do nothing */
10349 rest(1);
10350 }
10351
10352 comeback();
10353 register_blank_tiles();
10354 register_used_tiles();
10355 setup_combo_animations();
10356 setup_combo_animations2();
10357 int32_t ret = done-1;
10358 if(ret)
10359 {
10360 _selected_tile = tile;
10361 _selected_tcset = cs;
10362 }
10363
10364 popup_zqdialog_end();
10365 return ret;
10366 }
10367 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10368 {
10369 if(_selected_tile > -1)
10370 {
10371 tile = _selected_tile;
10372 cs = _selected_tcset;
10373 }
10374 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10375 if(_selected_tile < 0)
10376 {
10377 _selected_tile = tile;
10378 _selected_tcset = cs;
10379 }
10380 return ret;
10381 }
10382
10383 int32_t onTiles()
10384 {
10385 return onGotoTiles(-1);
10386 }
10387
10388 int32_t onGotoTiles(int32_t startfrom)
10389 {
10390 static int32_t t = 0;
10391 if (startfrom > -1)
10392 t = startfrom;
10393 int32_t f = 0;
10394 int32_t c = CSet;
10395 reset_pal_cycling();
10396 // loadlvlpal(Map.CurrScr()->color);
10397 rebuild_trans_table();
10398 select_tile(t, f, 0, c, true);
10399 refresh(rALL);
10400 return D_O_K;
10401 }
10402
10403 int32_t combopage_animate = 1;
10404 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10405 {
10406 if(unsigned(c)<MAXCOMBOS)
10407 {
10408 newcombo& cmb = combobuf[c];
10409 int t = cmb.tile;
10410 if(!animate)
10411 cmb.tile = cmb.o_tile;
10412 put_combo(dest,x,y,c,cs,0,0);
10413 cmb.tile = t;
10414 }
10415 else
10416 {
10417 rectfill(dest,x,y,x+32-1,y+32-1,0);
10418 }
10419 }
10420
10421 void draw_combos(int32_t page,int32_t cs,bool cols)
10422 {
10423 clear_bitmap(screen2);
10424 BITMAP *buf = create_bitmap_ex(8,16,16);
10425
10426 int32_t w = 32;
10427 int32_t h = 32;
10428 int32_t mul = 2;
10429
10430 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10431 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10432 int32_t screen_xofs=window_xofs+6;
10433 int32_t screen_yofs=window_yofs+25;
10434
10435 if(cols==false)
10436 {
10437 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10438 {
10439 int32_t x = (i%COMBOS_PER_ROW)*w;
10440 int32_t y = (i/COMBOS_PER_ROW)*h;
10441
10442 combotile_override_x = x+screen_xofs+(w-16)/2;
10443 combotile_override_y = y+screen_yofs+(h-16)/2;
10444 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10445 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10446 }
10447 }
10448 else
10449 {
10450 int32_t c = 0;
10451
10452 for(int32_t i=0; i<256; i++)
10453 {
10454 int32_t x = (i%COMBOS_PER_ROW)*w;
10455 int32_t y = (i/COMBOS_PER_ROW)*h;
10456
10457 combotile_override_x = x+screen_xofs+(w-16)/2;
10458 combotile_override_y = y+screen_yofs+(h-16)/2;
10459 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10460 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10461 ++c;
10462
10463 if((i&3)==3)
10464 c+=48;
10465
10466 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10467 c-=256;
10468 }
10469 }
10470 combotile_override_x = combotile_override_y = -1;
10471
10472 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10473 {
10474 vline(screen2,x,0,(208*mul)-1,vc(15));
10475 }
10476
10477 destroy_bitmap(buf);
10478 }
10479
10480 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10481 {
10482 int32_t yofs=3;
10483 static BITMAP *buf = create_bitmap_ex(8,16,16);
10484 int32_t mul = 2;
10485 FONT *tfont = get_zc_font(font_lfont_l);
10486
10487 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10488 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10489 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10490
10491 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10492
10493 if(copy>=0)
10494 {
10495 put_combo(buf,0,0,copy,cs,0,0);
10496 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10497
10498 if(copycnt>1)
10499 {
10500 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10501 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10502 }
10503 else
10504 {
10505 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10506 }
10507 }
10508 else
10509 {
10510 if (InvalidBG == 2)
10511 {
10512 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10513 }
10514 else if(InvalidBG == 1)
10515 {
10516 for(int32_t dy=0; dy<16*mul; dy++)
10517 {
10518 for(int32_t dx=0; dx<16*mul; dx++)
10519 {
10520 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10521 }
10522 }
10523 }
10524 else
10525 {
10526 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10527 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10528 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10529 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10530 }
10531 }
10532
10533 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10534 put_combo(buf,0,0,tile,cs,0,0);
10535 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10536
10537 if(tile>tile2)
10538 {
10539 zc_swap(tile,tile2);
10540 }
10541
10542 char cbuf[8];
10543 cbuf[0]=0;
10544
10545 if(tile2!=tile)
10546 {
10547 sprintf(cbuf,"-%d",tile2);
10548 }
10549
10550 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10551 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10552
10553 if(tile2==tile)
10554 {
10555 int32_t nextcombo=combobuf[tile].nextcombo;
10556 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10557 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10558
10559 if(nextcombo>0)
10560 {
10561 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10562 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10563 }
10564 else
10565 {
10566 if (InvalidBG == 2)
10567 {
10568 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10569 }
10570 else if(InvalidBG == 1)
10571 {
10572 for(int32_t dy=0; dy<16*mul; dy++)
10573 {
10574 for(int32_t dx=0; dx<16*mul; dx++)
10575 {
10576 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10577 }
10578 }
10579 }
10580 else
10581 {
10582 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10583 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10584 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10585 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10586 }
10587 }
10588
10589 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10590 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10591 }
10592
10593
10594 FONT *tf = font;
10595 font = tfont;
10596
10597 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10598 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10599
10600 if(buttons&2)
10601 {
10602 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10603 }
10604
10605 if(buttons&4)
10606 {
10607 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10608 }
10609
10610 font = tf;
10611
10612 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10613 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10614 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10615 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10616
10617 int32_t w = 640;
10618 int32_t h = 480;
10619 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10620 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10621 int32_t screen_xofs=window_xofs+6;
10622 int32_t screen_yofs=window_yofs+25;
10623
10624 custom_vsync();
10625 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10626 SCRFIX();
10627 //destroy_bitmap(buf);
10628 }
10629
10630 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10631 {
10632 int32_t page = tile&0xFF00;
10633 tile &= 0xFF;
10634
10635 if(!cols)
10636 tile += s;
10637 else
10638 {
10639 if(s==-COMBOS_PER_ROW)
10640 tile-=4;
10641
10642 if(s==COMBOS_PER_ROW)
10643 tile+=4;
10644
10645 if(s==-1)
10646 tile-=1;
10647
10648 if(s==1)
10649 tile+=1;
10650 }
10651
10652 /*
10653 if(s==1)
10654 {
10655 if((tile&3)==3)
10656 tile+=48;
10657 else
10658 ++tile;
10659 }
10660 if(s==-1)
10661 {
10662 if((tile&3)==0)
10663 tile-=48;
10664 else
10665 --tile;
10666 }
10667 }
10668 */
10669 bound(tile,0,255);
10670 tile += page;
10671
10672 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10673 tile2 = tile;
10674 }
10675
10676 void draw_combo_list_window()
10677 {
10678 int32_t window_xofs=0;
10679 int32_t window_yofs=0;
10680 int32_t w = 640;
10681 int32_t h = 480;
10682
10683 window_xofs=(zq_screen_w-w-12)>>1;
10684 window_yofs=(zq_screen_h-h-25-6)>>1;
10685 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10686 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10687 FONT *oldfont = font;
10688 font = get_zc_font(font_lfont);
10689 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10690 font=oldfont;
10691 }
10692
10693
10694 static int32_t _selected_combo=-1, _selected_cset=-1;
10695 bool select_combo_2(int32_t &cmb,int32_t &cs)
10696 {
10697 popup_zqdialog_start();
10698 reset_combo_animations();
10699 reset_combo_animations2();
10700 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10701 // static int32_t cmb=0;
10702 int32_t page=cmb>>8;
10703 int32_t tile2=cmb;
10704 int32_t done=0;
10705 int32_t tile_clicked=-1;
10706 int32_t t2;
10707 int32_t copy=-1;
10708 int32_t copycnt=0;
10709
10710 position_mouse_z(0);
10711
10712 go();
10713 int32_t w = 640;
10714 int32_t h = 480;
10715 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10716 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10717 int32_t screen_xofs=window_xofs+6;
10718 int32_t screen_yofs=window_yofs+25;
10719 int32_t panel_yofs=3;
10720 int32_t mul = 2;
10721 FONT *tfont = get_zc_font(font_lfont_l);
10722
10723 draw_combo_list_window();
10724 draw_combos(page,cs,combo_cols);
10725 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10726
10727 while(gui_mouse_b())
10728 {
10729 /* do nothing */
10730 rest(1);
10731 }
10732
10733 bool bdown=false;
10734 int32_t f=0;
10735 int otl = cmb, otl2 = tile2;
10736
10737 do
10738 {
10739 HANDLE_CLOSE_ZQDLG();
10740 if(exiting_program) break;
10741 rest(4);
10742 bool redraw=false;
10743
10744 if(mouse_z<0)
10745 {
10746 if(page<COMBO_PAGES-1)
10747 {
10748 ++page;
10749 cmb=tile2=(page<<8)+(cmb&0xFF);
10750 }
10751
10752 position_mouse_z(0);
10753 redraw=true;
10754 }
10755 else if(mouse_z>0)
10756 {
10757 if(page>0)
10758 {
10759 --page;
10760 cmb=tile2=(page<<8)+(cmb&0xFF);
10761 }
10762
10763 position_mouse_z(0);
10764 redraw=true;
10765 }
10766
10767 if(keypressed())
10768 {
10769 switch(readkey()>>8)
10770 {
10771 case KEY_DEL:
10772 cmb=0;
10773 done=2;
10774 break;
10775
10776 case KEY_ENTER_PAD:
10777 case KEY_ENTER:
10778 done=2;
10779 break;
10780
10781 case KEY_ESC:
10782 done=1;
10783 break;
10784
10785 case KEY_F1:
10786 onHelp();
10787 break;
10788
10789 case KEY_SPACE:
10790 combo_cols=!combo_cols;
10791 redraw=true;
10792 break;
10793
10794 case KEY_EQUALS:
10795 case KEY_PLUS_PAD:
10796 cs = (cs<13) ? cs+1:0;
10797 redraw=true;
10798 break;
10799
10800 case KEY_MINUS:
10801 case KEY_MINUS_PAD:
10802 cs = (cs>0) ? cs-1:13;
10803 redraw=true;
10804 break;
10805
10806 case KEY_UP:
10807 sel_combo(cmb,tile2,-COMBOS_PER_ROW,combo_cols);
10808 redraw=true;
10809 break;
10810
10811 case KEY_DOWN:
10812 sel_combo(cmb,tile2,COMBOS_PER_ROW,combo_cols);
10813 redraw=true;
10814 break;
10815
10816 case KEY_LEFT:
10817 sel_combo(cmb,tile2,-1,combo_cols);
10818 redraw=true;
10819 break;
10820
10821 case KEY_RIGHT:
10822 sel_combo(cmb,tile2,1,combo_cols);
10823 redraw=true;
10824 break;
10825
10826 case KEY_PGUP:
10827 if(page>0)
10828 {
10829 --page;
10830 cmb=tile2=(page<<8)+(cmb&0xFF);
10831 }
10832
10833 redraw=true;
10834 break;
10835
10836 case KEY_PGDN:
10837 if(page<COMBO_PAGES-1)
10838 {
10839 ++page;
10840 cmb=tile2=(page<<8)+(cmb&0xFF);
10841 }
10842
10843 redraw=true;
10844 break;
10845
10846 case KEY_P:
10847 {
10848 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10849
10850 if(!cancelgetnum)
10851 page=(zc_min(choosepage,COMBO_PAGES-1));
10852
10853 cmb=tile2=(page<<8)+(cmb&0xFF);
10854 redraw=true;
10855 break;
10856 }
10857 }
10858
10859 clear_keybuf();
10860 }
10861
10862 if(gui_mouse_b()&1)
10863 {
10864 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10865 {
10866 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10867 {
10868 done=1;
10869 }
10870 }
10871
10872 int32_t x=gui_mouse_x()-screen_xofs;
10873 int32_t y=gui_mouse_y()-screen_yofs;
10874
10875 if(y>=0 && y<208*mul)
10876 {
10877 x=zc_min(zc_max(x,0),(320*mul)-1);
10878 int32_t t;
10879
10880 if(!combo_cols)
10881 {
10882 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10883 }
10884 else
10885 {
10886 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10887 }
10888
10889 bound(t,0,255);
10890 t+=page<<8;
10891 cmb=tile2=t;
10892
10893 if(tile_clicked!=t)
10894 {
10895 dclick_status=DCLICK_NOT;
10896 }
10897 else if(dclick_status == DCLICK_AGAIN)
10898 {
10899 while(gui_mouse_b())
10900 {
10901 /* do nothing */
10902 }
10903
10904 if(!combo_cols)
10905 {
10906 t2 = (y>>5)*COMBOS_PER_ROW + (x>>5);
10907 }
10908 else
10909 {
10910 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10911 }
10912
10913 if(t2!=t)
10914 {
10915 dclick_status=DCLICK_NOT;
10916 }
10917 else
10918 {
10919 done=2;
10920 }
10921 }
10922
10923 tile_clicked=t;
10924 }
10925 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10926 {
10927 if(y<(224*mul)+panel_yofs && page>0)
10928 {
10929 --page;
10930 redraw=true;
10931 }
10932
10933 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10934 {
10935 ++page;
10936 redraw=true;
10937 }
10938
10939 bdown=true;
10940 }
10941
10942 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10943 {
10944 FONT *tf = font;
10945 font = tfont;
10946
10947 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10948 {
10949 done=2;
10950 }
10951
10952 font = tf;
10953 }
10954 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
10955 {
10956 FONT *tf = font;
10957 font = tfont;
10958
10959 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
10960 combopage_animate = combopage_animate ? 0 : 1;
10961 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
10962 redraw = true;
10963
10964 font = tf;
10965 }
10966
10967 bdown=true;
10968 }
10969
10970 bool r_click = false;
10971
10972 if(gui_mouse_b()&2 && !bdown)
10973 {
10974 int32_t x=gui_mouse_x()+screen_xofs;
10975 int32_t y=gui_mouse_y()+screen_yofs;
10976
10977 if(y>=0 && y<208*mul)
10978 {
10979 x=zc_min(zc_max(x,0),(320*mul)-1);
10980 int32_t t;
10981
10982 if(!combo_cols)
10983 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
10984 else
10985 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10986
10987 bound(t,0,255);
10988 t+=page<<8;
10989
10990 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
10991 cmb=tile2=t;
10992 }
10993
10994 bdown = r_click = true;
10995 f=8;
10996 }
10997
10998 if(gui_mouse_b()==0)
10999 bdown=false;
11000
11001 if((f%8) || InvalidBG == 1)
11002 redraw = true;
11003 if(otl != cmb || otl2 != tile2)
11004 {
11005 otl = cmb;
11006 otl2 = tile2;
11007 redraw = true;
11008 }
11009
11010 if(redraw || combopage_animate)
11011 draw_combos(page,cs,combo_cols);
11012
11013 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11014
11015 if(f&8)
11016 {
11017 int32_t x,y;
11018
11019 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11020 {
11021 if((i>>8)==page)
11022 {
11023 int32_t t=i&255;
11024
11025 if(!combo_cols)
11026 {
11027 x=(t%COMBOS_PER_ROW)<<5;
11028 y=(t/COMBOS_PER_ROW)<<5;
11029 }
11030 else
11031 {
11032 x=((t&3) + ((t/52)<<2)) << 5;
11033 y=((t%52)>>2) << 5;
11034 }
11035
11036 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11037 }
11038 }
11039
11040 SCRFIX();
11041 }
11042
11043 ++f;
11044
11045 }
11046 while(!done);
11047
11048 while(gui_mouse_b())
11049 {
11050 /* do nothing */
11051 rest(1);
11052 }
11053
11054 comeback();
11055 setup_combo_animations();
11056 setup_combo_animations2();
11057
11058 bool ret = done==2;
11059 if(ret)
11060 {
11061 _selected_combo = cmb;
11062 _selected_cset = cs;
11063 }
11064
11065 popup_zqdialog_end();
11066 return ret;
11067 }
11068
11069 bool select_combo_3(int32_t &cmb,int32_t &cs)
11070 {
11071 if(_selected_combo < 0)
11072 {
11073 _selected_combo = Combo;
11074 _selected_cset = CSet;
11075 }
11076 cmb = _selected_combo;
11077 cs = _selected_cset;
11078 return select_combo_2(cmb,cs);
11079 }
11080
11081 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11082 {
11083 static bitstring pasteflags;
11084 static const vector<CheckListInfo> advp_names =
11085 {
11086 { "Tile" },
11087 { "CSet2" },
11088 { "Solidity" },
11089 { "Animation" },
11090 { "Type" },
11091 { "Inherent Flag" },
11092 { "Attribytes" },
11093 { "Attrishorts" },
11094 { "Attributes" },
11095 { "Flags", "The 16 Flags on the 'Flags' tab" },
11096 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11097 { "Label" },
11098 { "Script" },
11099 { "Effect" },
11100 { "Triggers Tab" },
11101 { "Lifting Tab" },
11102 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11103 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11104 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11105 };
11106 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11107 return false;
11108
11109 //Paste to each combo in the range
11110 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11111 {
11112 combobuf[i].advpaste(combobuf[copy], pasteflags);
11113 }
11114
11115 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11116 {
11117 setup_combo_animations();
11118 setup_combo_animations2();
11119 }
11120
11121 return true;
11122 }
11123
11124 int32_t combo_screen(int32_t pg, int32_t tl)
11125 {
11126 popup_zqdialog_start();
11127 reset_combo_animations();
11128 reset_combo_animations2();
11129 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11130 static int32_t tile=0;
11131 static int32_t page=0;
11132
11133 if(pg>-1)
11134 page = pg;
11135
11136 if(tl>-1)
11137 tile = tl;
11138
11139 int32_t tile2=tile;
11140 int32_t done=0;
11141 int32_t cs = CSet;
11142 int32_t copy=-1;
11143 int32_t copycnt=0;
11144
11145 int32_t tile_clicked=-1;
11146 int32_t t2;
11147
11148 bool masscopy;
11149
11150 go();
11151 int32_t w = 640;
11152 int32_t h = 480;
11153 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11154 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11155 int32_t screen_xofs=window_xofs+6;
11156 int32_t screen_yofs=window_yofs+25;
11157 int32_t panel_yofs=3;
11158 int32_t mul = 2;
11159 FONT *tfont = get_zc_font(font_lfont_l);
11160
11161 draw_combo_list_window();
11162 draw_combos(page,cs,combo_cols);
11163 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11164 go_combos();
11165 position_mouse_z(0);
11166
11167 while(gui_mouse_b())
11168 {
11169 /* do nothing */
11170 }
11171
11172 bool bdown=false;
11173 int32_t f=0;
11174 int otl = tile, otl2 = tile2;
11175
11176 do
11177 {
11178 HANDLE_CLOSE_ZQDLG();
11179 if(exiting_program) break;
11180 rest(4);
11181 bool redraw=false;
11182
11183 if(mouse_z<0)
11184 {
11185 if(page<COMBO_PAGES-1)
11186 {
11187 ++page;
11188 tile=tile2=(page<<8)+(tile&0xFF);
11189 }
11190
11191 position_mouse_z(0);
11192 redraw=true;
11193 }
11194 else if(mouse_z>0)
11195 {
11196 if(page>0)
11197 {
11198 --page;
11199 tile=tile2=(page<<8)+(tile&0xFF);
11200 }
11201
11202 position_mouse_z(0);
11203 redraw=true;
11204 }
11205
11206 if(keypressed())
11207 {
11208 switch(readkey()>>8)
11209 {
11210 case KEY_ENTER_PAD:
11211 case KEY_ENTER:
11212 done=2;
11213 break;
11214
11215 case KEY_ESC:
11216 done=1;
11217 break;
11218
11219 case KEY_F1:
11220 onHelp();
11221 break;
11222
11223 case KEY_SPACE:
11224 combo_cols=!combo_cols;
11225 redraw=true;
11226 break;
11227
11228 case KEY_EQUALS:
11229 case KEY_PLUS_PAD:
11230 if(CHECK_CTRL_CMD)
11231 {
11232 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11233 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11234 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11235
11236 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11237 {
11238 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11239 0, NEWMAXTILES-1));
11240 }
11241
11242 setup_combo_animations();
11243 redraw=true;
11244 }
11245 else
11246 {
11247 cs = (cs<13) ? cs+1:0;
11248 redraw=true;
11249 }
11250
11251 break;
11252
11253 case KEY_MINUS:
11254 case KEY_MINUS_PAD:
11255 if(CHECK_CTRL_CMD)
11256 {
11257 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11258 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11259 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11260
11261 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11262 {
11263 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11264 0, NEWMAXTILES-1));
11265 }
11266
11267 setup_combo_animations();
11268 redraw=true;
11269 }
11270 else
11271 {
11272 cs = (cs>0) ? cs-1:13;
11273 redraw=true;
11274 }
11275
11276 break;
11277
11278 case KEY_UP:
11279 sel_combo(tile,tile2,-COMBOS_PER_ROW,combo_cols);
11280 redraw=true;
11281 break;
11282
11283 case KEY_DOWN:
11284 sel_combo(tile,tile2,COMBOS_PER_ROW,combo_cols);
11285 redraw=true;
11286 break;
11287
11288 case KEY_LEFT:
11289 sel_combo(tile,tile2,-1,combo_cols);
11290 redraw=true;
11291 break;
11292
11293 case KEY_RIGHT:
11294 sel_combo(tile,tile2,1,combo_cols);
11295 redraw=true;
11296 break;
11297
11298 case KEY_PGUP:
11299 if(page>0)
11300 {
11301 --page;
11302 tile=tile2=(page<<8)+(tile&0xFF);
11303 }
11304
11305 redraw=true;
11306 break;
11307
11308 case KEY_PGDN:
11309 if(page<COMBO_PAGES-1)
11310 {
11311 ++page;
11312 tile=tile2=(page<<8)+(tile&0xFF);
11313 }
11314
11315 redraw=true;
11316 break;
11317
11318 case KEY_A:
11319 {
11320 tile=(page<<8);
11321 tile2=(page<<8)+(0xFF);
11322 }
11323
11324 redraw=true;
11325 break;
11326
11327 case KEY_P:
11328 {
11329 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11330
11331 if(!cancelgetnum)
11332 page=(zc_min(choosepage,COMBO_PAGES-1));
11333
11334 tile=tile2=(page<<8)+(tile&0xFF);
11335 redraw=true;
11336 }
11337 break;
11338
11339 case KEY_U:
11340 comeback_combos();
11341 redraw=true;
11342 break;
11343
11344 case KEY_E:
11345 go_combos();
11346 edit_combo(tile,false,cs);
11347 redraw=true;
11348 setup_combo_animations();
11349 setup_combo_animations2();
11350 break;
11351
11352 case KEY_C:
11353 go_combos();
11354 copy=zc_min(tile,tile2);
11355 copycnt=abs(tile-tile2)+1;
11356 redraw=true;
11357 break;
11358
11359 case KEY_H:
11360 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11361 {
11362 combobuf[i].flip^=1;
11363 byte w2=combobuf[i].walk;
11364 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11365 w2=combobuf[i].csets;
11366 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11367 }
11368
11369 redraw=true;
11370 saved=false;
11371 break;
11372
11373 case KEY_M:
11374 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11375 {
11376 move_combos(tile,tile2,copy,copycnt);
11377 saved=false;
11378 }
11379
11380 redraw=true;
11381 break;
11382
11383 case KEY_S:
11384 tile=tile2=zc_min(tile,tile2);
11385
11386 if(copy>=0 && tile!=copy)
11387 {
11388 go_combos();
11389
11390 for(int32_t i=0; i<copycnt; i++)
11391 {
11392 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11393 }
11394
11395 saved=false;
11396 setup_combo_animations();
11397 setup_combo_animations2();
11398 }
11399
11400 redraw=true;
11401 copy=-1;
11402 break;
11403
11404 case KEY_V:
11405 if((CHECK_CTRL_CMD) && copy != -1)
11406 {
11407 if(advpaste(tile, tile2, copy))
11408 {
11409 saved=false;
11410 redraw=true;
11411 copy=-1;
11412 }
11413
11414 break;
11415 }
11416
11417 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11418
11419 if(copy==-1)
11420 {
11421 go_combos();
11422
11423 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11424 {
11425 combobuf[i].flip^=2;
11426 byte w2=combobuf[i].walk;
11427 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11428 w2=combobuf[i].csets;
11429 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11430 }
11431
11432 saved=false;
11433 }
11434 else
11435 {
11436 go_combos();
11437 copy_combos(tile,tile2,copy,copycnt,masscopy);
11438 setup_combo_animations();
11439 setup_combo_animations2();
11440 saved=false;
11441 }
11442
11443 redraw=true;
11444 break;
11445 case KEY_R:
11446 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11447 {
11448 combobuf[i].flip = rotate_value(combobuf[i].flip);
11449 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11450 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11451 }
11452
11453 redraw=true;
11454 saved=false;
11455 break;
11456
11457 case KEY_I:
11458 {
11459 // rev.1509; Can now insert/remove all selected combos
11460 int32_t z=tile;
11461 int32_t numSelected = abs(tile-tile2) + 1;
11462 tile=zc_min(tile,tile2);
11463 tile2=MAXCOMBOS;
11464 copy = tile + numSelected; // copy=tile+1;
11465 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11466
11467 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11468 {
11469 char buf[64];
11470
11471 if(numSelected>1)
11472 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11473 else
11474 sprintf(buf,"Remove combo %d?",tile);
11475
11476 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11477 {
11478 move_combos(tile,tile2,copy, copycnt);
11479 //don't allow the user to undo; quest combo references are incorrect -DD
11480 go_combos();
11481 redraw=true;
11482 saved=false;
11483 }
11484 }
11485 else
11486 {
11487 char buf[64];
11488
11489 if(numSelected>1)
11490 sprintf(buf,"Insert %d blank combos?",numSelected);
11491 else
11492 sprintf(buf,"Insert a blank combo?");
11493
11494 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11495 {
11496 move_combos(copy,tile2,tile, copycnt);
11497 go_combos();
11498 redraw=true;
11499 saved=false;
11500 }
11501 }
11502
11503 copy=-1;
11504 tile2=tile=z;
11505 }
11506 break;
11507
11508 case KEY_DEL:
11509 {
11510 char buf[40];
11511
11512 if(tile==tile2)
11513 {
11514 sprintf(buf,"Delete combo %d?",tile);
11515 }
11516 else
11517 {
11518 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11519 }
11520
11521 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11522 {
11523 go_combos();
11524
11525 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11526 {
11527 clear_combo(i);
11528 }
11529
11530 tile=tile2=zc_min(tile,tile2);
11531 redraw=true;
11532 saved=false;
11533 setup_combo_animations();
11534 setup_combo_animations2();
11535 }
11536 }
11537 break;
11538 }
11539
11540 clear_keybuf();
11541 }
11542
11543 if(gui_mouse_b()&1)
11544 {
11545 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11546 {
11547 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11548 {
11549 done=1;
11550 }
11551 }
11552
11553 int32_t x=gui_mouse_x()-screen_xofs;
11554 int32_t y=gui_mouse_y()-screen_yofs;
11555
11556 if(y>=0 && y<(208*mul))
11557 {
11558 x=zc_min(zc_max(x,0),(320*mul)-1);
11559 int32_t t;
11560
11561 if(!combo_cols)
11562 {
11563 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11564 }
11565 else
11566 {
11567 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11568 }
11569
11570 bound(t,0,255);
11571 t+=page<<8;
11572
11573 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11574 {
11575 tile2=t;
11576 }
11577 else
11578 {
11579 tile=tile2=t;
11580 }
11581
11582 if(tile_clicked!=t)
11583 {
11584 dclick_status=DCLICK_NOT;
11585 }
11586 else if(dclick_status == DCLICK_AGAIN)
11587 {
11588 while(gui_mouse_b())
11589 {
11590 /* do nothing */
11591 rest(1);
11592 }
11593
11594 if(!combo_cols)
11595 {
11596 t2 = (y>>4)*COMBOS_PER_ROW + (x>>4);
11597 }
11598 else
11599 {
11600 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11601 }
11602
11603 bound(t2,0,255);
11604 t2+=page<<8;
11605
11606 if(t2!=t)
11607 {
11608 dclick_status=DCLICK_NOT;
11609 }
11610 else
11611 {
11612 go_combos();
11613 edit_combo(tile,false,cs);
11614 redraw=true;
11615 setup_combo_animations();
11616 setup_combo_animations2();
11617 }
11618 }
11619
11620 tile_clicked=t;
11621 }
11622 else if(x>(300*mul) && !bdown)
11623 {
11624 if(y<(224*mul)+panel_yofs && page>0)
11625 {
11626 --page;
11627 redraw=true;
11628 }
11629
11630 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11631 {
11632 ++page;
11633 redraw=true;
11634 }
11635
11636 bdown=true;
11637 }
11638
11639 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11640 {
11641 FONT *tf = font;
11642 font = tfont;
11643
11644 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11645 {
11646 font = tf;
11647 edit_combo(tile,false,cs);
11648 redraw=true;
11649 }
11650
11651 font = tf;
11652 }
11653 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11654 {
11655 FONT *tf = font;
11656 font = tfont;
11657
11658 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11659 {
11660 done=1;
11661 }
11662
11663 font = tf;
11664 }
11665 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11666 {
11667 FONT *tf = font;
11668 font = tfont;
11669
11670 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11671 combopage_animate = combopage_animate ? 0 : 1;
11672 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11673 redraw = true;
11674
11675 font = tf;
11676 }
11677
11678 bdown=true;
11679 }
11680
11681 bool r_click = false;
11682
11683 if(gui_mouse_b()&2 && !bdown)
11684 {
11685 int32_t x=gui_mouse_x()-screen_xofs;
11686 int32_t y=gui_mouse_y()-screen_yofs;
11687
11688 if(y>=0 && y<(208*mul))
11689 {
11690 x=zc_min(zc_max(x,0),(320*mul)-1);
11691 int32_t t;
11692
11693 if(!combo_cols)
11694 {
11695 t = (y>>5)*COMBOS_PER_ROW + (x>>5);
11696 }
11697 else
11698 {
11699 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11700 }
11701
11702 bound(t,0,255);
11703 t+=page<<8;
11704
11705 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11706 {
11707 tile=tile2=t;
11708 }
11709 }
11710
11711 bdown = r_click = true;
11712 f=8;
11713 }
11714
11715 REDRAW:
11716
11717 if(gui_mouse_b()==0)
11718 bdown=false;
11719
11720 if((f%8) || InvalidBG == 1)
11721 redraw = true;
11722 if(otl != tile || otl2 != tile2)
11723 {
11724 otl = tile;
11725 otl2 = tile2;
11726 redraw = true;
11727 }
11728
11729 if(redraw || combopage_animate)
11730 draw_combos(page,cs,combo_cols);
11731
11732 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11733
11734 if(f&8)
11735 {
11736 int32_t x,y;
11737
11738 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11739 {
11740 if((i>>8)==page)
11741 {
11742 int32_t t=i&255;
11743
11744 if(!combo_cols)
11745 {
11746 x=(t%COMBOS_PER_ROW)<<5;
11747 y=(t/COMBOS_PER_ROW)<<5;
11748 }
11749 else
11750 {
11751 x=((t&3) + ((t/52)<<2)) << 5;
11752 y=((t%52)>>2) << 5;
11753 }
11754
11755 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11756 }
11757 }
11758
11759 SCRFIX();
11760 }
11761
11762 ++f;
11763
11764 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11765 if(r_click)
11766 {
11767 NewMenu rcmenu
11768 {
11769 { "Copy", [&]()
11770 {
11771 go_combos();
11772 copy=zc_min(tile,tile2);
11773 copycnt=abs(tile-tile2)+1;
11774 } },
11775 { "Paste", [&]()
11776 {
11777 if((CHECK_CTRL_CMD) && copy != -1)
11778 {
11779 if(advpaste(tile, tile2, copy))
11780 {
11781 saved=false;
11782 redraw=true;
11783 copy=-1;
11784 }
11785 return;
11786 }
11787
11788 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11789
11790 if(copy>-1)
11791 {
11792 go_combos();
11793 copy_combos(tile,tile2,copy,copycnt,masscopy);
11794 setup_combo_animations();
11795 setup_combo_animations2();
11796 saved=false;
11797 }
11798 } },
11799 { "Adv. Paste", [&]()
11800 {
11801 if(copy > -1)
11802 {
11803 if(advpaste(tile, tile2, copy))
11804 {
11805 saved=false;
11806 redraw=true;
11807 copy=-1;
11808 }
11809 }
11810 } },
11811 { "Swap", [&]()
11812 {
11813 tile=tile2=zc_min(tile,tile2);
11814
11815 if(copy>=0 && tile!=copy)
11816 {
11817 go_combos();
11818
11819 for(int32_t i=0; i<copycnt; i++)
11820 {
11821 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11822 }
11823
11824 saved=false;
11825 setup_combo_animations();
11826 setup_combo_animations2();
11827 }
11828 copy=-1;
11829 } },
11830 { "Delete", [&]()
11831 {
11832 string msg;
11833
11834 if(tile==tile2)
11835 msg = fmt::format("Delete combo {}?",tile);
11836 else
11837 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11838 bool didconfirm = false;
11839 AlertDialog("Confirm Delete",msg,
11840 [&](bool ret,bool)
11841 {
11842 if(ret)
11843 didconfirm = true;
11844 }).show();
11845 if(didconfirm)
11846 {
11847 go_combos();
11848
11849 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11850 clear_combo(i);
11851
11852 tile=tile2=zc_min(tile,tile2);
11853 saved=false;
11854 }
11855 } },
11856 {},
11857 { "Edit", [&]()
11858 {
11859 go_combos();
11860 edit_combo(tile,false,cs);
11861 } },
11862 { "Insert", [&]()
11863 {
11864 int z = tile;
11865 int count = abs(tile-tile2)+1;
11866 tile = zc_min(tile,tile2);
11867 tile2 = MAXCOMBOS;
11868 copy = tile+count;
11869 copycnt = MAXCOMBOS-tile-count;
11870
11871 string msg;
11872
11873 if(count>1)
11874 msg = fmt::format("Insert combos {} - {}?"
11875 " This will offset all of the combos that follow!",tile, copy-1);
11876 else
11877 msg = fmt::format("Insert combo {}?"
11878 " This will offset all of the combos that follow!",tile);
11879
11880 bool didconfirm = false;
11881 AlertDialog("Confirm Insert",msg,
11882 [&](bool ret,bool)
11883 {
11884 if(ret)
11885 didconfirm = true;
11886 }).show();
11887 if(didconfirm)
11888 move_combos(copy, tile2, tile, copycnt);
11889 else return;
11890
11891 copy = -1;
11892 tile2 = tile = z;
11893
11894 //don't allow the user to undo; quest combo references are incorrect -DD
11895 go_combos();
11896 saved = false;
11897 } },
11898 { "Remove", [&]()
11899 {
11900 int z = tile;
11901 int count = abs(tile-tile2)+1;
11902 tile = zc_min(tile,tile2);
11903 tile2 = MAXCOMBOS;
11904 copy = tile+count;
11905 copycnt = MAXCOMBOS-tile-count;
11906
11907 string msg;
11908
11909 if(count>1)
11910 msg = fmt::format("Remove combos {} - {}?"
11911 " This will offset all of the combos that follow!",tile, copy-1);
11912 else
11913 msg = fmt::format("Remove combo {}?"
11914 " This will offset all of the combos that follow!",tile);
11915
11916 bool didconfirm = false;
11917 AlertDialog("Confirm Remove",msg,
11918 [&](bool ret,bool)
11919 {
11920 if(ret)
11921 didconfirm = true;
11922 }).show();
11923 if(didconfirm)
11924 move_combos(tile, tile2, copy, copycnt);
11925 else return;
11926
11927 copy = -1;
11928 tile2 = tile = z;
11929
11930 //don't allow the user to undo; quest combo references are incorrect -DD
11931 go_combos();
11932 saved = false;
11933 } },
11934 {},
11935 { "Locations", [&]()
11936 {
11937 int32_t z = Combo;
11938 Combo = tile;
11939 onComboLocationReport();
11940 Combo = z;
11941 } },
11942 };
11943 rcmenu.pop(window_mouse_x(),window_mouse_y());
11944 redraw = true;
11945 r_click = false;
11946 goto REDRAW;
11947 }
11948
11949 }
11950 while(!done);
11951
11952 while(gui_mouse_b())
11953 rest(1);
11954 comeback();
11955 setup_combo_animations();
11956 setup_combo_animations2();
11957 _selected_combo = tile;
11958 _selected_cset = cs;
11959 popup_zqdialog_end();
11960 return done-1;
11961 }
11962
11963 int32_t onCombos()
11964 {
11965 // reset_combo_animations();
11966 combo_screen(-1,-1);
11967 // setup_combo_animations();
11968 refresh(rALL);
11969 return D_O_K;
11970 }
11971
11972 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11973 {
11974 //these are here to bypass compiler warnings about unused arguments
11975 d=d;
11976 c=c;
11977
11978 if(msg==MSG_CLICK)
11979 {
11980 int32_t t=curr_combo.o_tile;
11981 int32_t f=curr_combo.flip;
11982
11983 if(select_tile(t,f,1,CSet,true,0,true))
11984 {
11985 curr_combo.tile=t;
11986 curr_combo.o_tile=t;
11987 curr_combo.flip=f;
11988 return D_REDRAW;
11989 }
11990 }
11991
11992 return D_O_K;
11993 }
11994
11995 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11996 {
11997 //these are here to bypass compiler warnings about unused arguments
11998 c=c;
11999
12000 if(msg==MSG_DRAW)
12001 {
12002 FONT *f = get_zc_font(font_lfont_l);
12003 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12004 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12005 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12006 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12007 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12008 }
12009
12010 return D_O_K;
12011 }
12012
12013 int32_t click_d_ctile_proc()
12014 {
12015 d_ctile_proc(MSG_CLICK,NULL,0);
12016 return D_REDRAW;
12017 }
12018
12019 int32_t click_d_combo_proc();
12020
12021 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12022 {
12023 if(index<0)
12024 {
12025 *list_size = bidcomboscripts_cnt;
12026 return NULL;
12027 }
12028
12029 return bidcomboscripts[index].first.c_str();
12030 }
12031 9 ListData comboscript_list(comboscriptdroplist, &font);
12032
12033 bool call_combo_editor(int32_t);
12034 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12035 {
12036 FONT* ofont = font;
12037 //CSet = cs;
12038 reset_combo_animations();
12039 reset_combo_animations2();
12040 bool edited = call_combo_editor(c);
12041 font = ofont;
12042
12043 if(freshen)
12044 {
12045 refresh(rALL);
12046 }
12047
12048 setup_combo_animations();
12049 setup_combo_animations2();
12050
12051 return edited;
12052 }
12053
12054 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12055 {
12056 switch(msg)
12057 {
12058 case MSG_CLICK:
12059 {
12060 int32_t cs = d->d2;
12061 int32_t f = 0;
12062
12063 if(select_tile(d->d1,f,1,cs,true))
12064 {
12065 int32_t ok=1;
12066
12067 if(newtilebuf[d->d1].format==tf8Bit)
12068 jwin_alert("Warning",
12069 "You have selected an 8-bit tile.",
12070 "It will not be drawn correctly",
12071 "on the file select screen.",
12072 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12073
12074 return D_REDRAW;
12075 }
12076 }
12077 break;
12078
12079 case MSG_DRAW:
12080 d->w = 32+4;
12081 d->h = 32+4;
12082
12083 BITMAP *buf = create_bitmap_ex(8,16,16);
12084 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12085
12086 if(buf && bigbmp)
12087 {
12088 clear_bitmap(buf);
12089 overtile16(buf,d->d1,0,0,d->fg,0);
12090 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12091 destroy_bitmap(buf);
12092 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12093 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12094 destroy_bitmap(bigbmp);
12095 }
12096
12097 break;
12098 }
12099
12100 return D_O_K;
12101 }
12102
12103 static DIALOG icon_dlg[] =
12104 {
12105 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12106 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12107 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12108 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12109 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12110 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12111 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12112 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12113 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12114 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12115 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12116 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12117 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12118 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12119 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12120 };
12121
12122 int32_t onIcons()
12123 {
12124 PALETTE pal;
12125 // pal = RAMpal;
12126 memcpy(pal,RAMpal,sizeof(RAMpal));
12127 icon_dlg[0].dp2=get_zc_font(font_lfont);
12128
12129 for(int32_t i=0; i<4; i++)
12130 {
12131 icon_dlg[i+2].d1 = QMisc.icons[i];
12132 icon_dlg[i+2].fg = i+6;
12133 load_cset(pal, i+6, pSprite(i+spICON1));
12134 }
12135
12136 zc_set_palette(pal);
12137
12138 large_dialog(icon_dlg);
12139
12140 int32_t ret = do_zqdialog(icon_dlg,7);
12141
12142 if(ret==6)
12143 {
12144 for(int32_t i=0; i<4; i++)
12145 {
12146 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12147 {
12148 QMisc.icons[i] = icon_dlg[i+2].d1;
12149 saved=false;
12150 }
12151 }
12152 }
12153
12154 zc_set_palette(RAMpal);
12155 return D_O_K;
12156 }
12157
12158 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12159 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12160 {
12161 if(msg == MSG_DRAW)
12162 {
12163 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12164 }
12165
12166 return D_O_K;
12167 }
12168
12169 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12170 {
12171 switch(msg)
12172 {
12173 case MSG_CLICK:
12174 {
12175 if((d->flags&D_NOCLICK))
12176 break;
12177
12178 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12179 int32_t combo2;
12180 int32_t cs;
12181
12182 if(CHECK_ALT) //place selected cmb/cs
12183 {
12184 if(gui_mouse_b()&1)
12185 {
12186 if(!CHECK_SHIFT)
12187 d->d1 = Combo;
12188 d->fg = CSet;
12189 }
12190
12191 return ret|D_REDRAW;
12192 }
12193 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12194 {
12195 d->d1=0;
12196 d->fg=0;
12197 return ret|D_REDRAW;
12198 }
12199 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12200 {
12201 combo2=d->d1;
12202 cs=d->fg;
12203
12204 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12205 {
12206 d->d1=combo2;
12207 d->fg=cs;
12208 }
12209
12210 return ret|D_REDRAW;
12211 }
12212 else return ret|D_REDRAWME;
12213 }
12214 break;
12215
12216 case MSG_DRAW:
12217 {
12218 d->w = 32;
12219 d->h = 32;
12220
12221 BITMAP *buf = create_bitmap_ex(8,16,16);
12222 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12223
12224 if(buf && bigbmp)
12225 {
12226 clear_bitmap(buf);
12227
12228 if(d->d1==-1) // Display curr_combo instead of combobuf
12229 {
12230 newcombo hold = combobuf[0];
12231 combobuf[0] = curr_combo;
12232 putcombo(buf,0,0,0,d->fg);
12233 combobuf[0] = hold;
12234 }
12235 else if(d->d1)
12236 {
12237 putcombo(buf,0,0,d->d1,d->fg);
12238 }
12239
12240 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12241 destroy_bitmap(buf);
12242 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12243 destroy_bitmap(bigbmp);
12244 }
12245 }
12246 break;
12247 }
12248 return D_O_K;
12249 }
12250
12251 // Hey, let's have a few hundred more lines of code, why not.
12252
12253 #define MR_4BIT 0
12254 #define MR_8BIT 1
12255
12256 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12257 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12258 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12259
12260 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12261 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12262
12263 static int32_t massRecolorDraggedColor=-1;
12264 static int32_t massRecolorCSet;
12265 static bool massRecolorIgnoreBlank=true;
12266 static byte massRecolorType=MR_4BIT;
12267
12268 // Shows the sets of colors to replace from/to.
12269 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12270 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12271 #define D_CSET D_USER
12272 #define D_SETTABLE (D_USER<<1)
12273 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12274 {
12275 BITMAP* bmp=screen;
12276 int32_t colorWidth=(d->w-4)/16;
12277 byte* colors=static_cast<byte*>(d->dp);
12278
12279 switch(msg)
12280 {
12281 case MSG_DRAW:
12282 {
12283 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12284
12285 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12286 for(int32_t c=0; c<16; c++)
12287 {
12288 rectfill(bmp,
12289 d->x+2+c*colorWidth, d->y+2,
12290 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12291 baseColor+colors[c]);
12292 }
12293 }
12294 break;
12295
12296 case MSG_LPRESS:
12297 {
12298 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12299
12300 if(x >= 0 && x < 16) //sanity check!
12301 {
12302 massRecolorDraggedColor=colors[x];
12303 }
12304 }
12305 break;
12306
12307 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12308 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12309 {
12310 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12311 if(x >= 0 && x < 16) //sanity check!
12312 {
12313 colors[x]=massRecolorDraggedColor;
12314 d->flags|=D_DIRTY;
12315 }
12316 }
12317 massRecolorDraggedColor=-1;
12318 break;
12319 }
12320
12321 return D_O_K;
12322 }
12323
12324 // Used for the full palette in 8-bit mode.
12325 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12326 {
12327 BITMAP* bmp=screen;
12328 int colorWidth=(d->w-4)/16;
12329 d->h = 4+(colorWidth*14);
12330 int colorHeight=colorWidth;
12331
12332 switch(msg)
12333 {
12334 case MSG_DRAW:
12335 {
12336 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12337 for(int cset=0; cset<=13; cset++)
12338 {
12339 for(int color=0; color<16; color++)
12340 {
12341 rectfill(bmp,
12342 d->x+2+color*colorWidth,
12343 d->y+2+cset*colorHeight,
12344 d->x+2+((color+1)*colorWidth)-1,
12345 d->y+2+((cset+1)*colorHeight)-1,
12346 cset*16+color);
12347 }
12348 }
12349 }
12350 break;
12351
12352 case MSG_LPRESS:
12353 {
12354 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12355 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12356 massRecolorDraggedColor=cset*16+color;
12357 }
12358 break;
12359 }
12360
12361 return D_O_K;
12362 }
12363
12364 static DIALOG recolor_4bit_dlg[] =
12365 {
12366 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12367 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12368
12369 // 1
12370 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12371 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12372 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12373 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12374
12375 // 5
12376 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12377 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12378 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12379 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12380 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12381 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12382 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12383 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12384 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12385 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12386 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12387 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12388 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12389 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12390 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12391
12392 // 20
12393 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12394 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12395 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12396 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12397 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12398
12399 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12400 };
12401
12402 #define MR4_SRC_COLORS 2
12403 #define MR4_DEST_COLORS 4
12404 #define MR4_8BIT_EFFECT_START 6
12405 #define MR4_IGNORE_BLANK 20
12406 #define MR4_RESET 21
12407 #define MR4_SWITCH 22
12408 #define MR4_OK 23
12409 #define MR4_CANCEL 24
12410
12411 static DIALOG recolor_8bit_dlg[] =
12412 {
12413 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12414 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12415
12416 // 1
12417 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12418 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12419 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12420 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12421 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12422
12423 // 6
12424 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12425 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12426 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12427 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12428 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12429
12430 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12431 };
12432
12433 #define MR8_SRC_COLORS 2
12434 #define MR8_DEST_COLORS 4
12435 #define MR8_PALETTE 5
12436 #define MR8_IGNORE_BLANK 6
12437 #define MR8_RESET 7
12438 #define MR8_SWITCH 8
12439 #define MR8_OK 9
12440 #define MR8_CANCEL 10
12441
12442 static void massRecolorInit(int32_t cset)
12443 {
12444 massRecolorDraggedColor=-1;
12445 massRecolorCSet=cset;
12446
12447 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12448 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12449
12450 for(int32_t i=0; i<=13; i++)
12451 {
12452 if((massRecolor8BitCSets&(1<<i))!=0)
12453 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12454 else
12455 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12456 }
12457
12458 if(massRecolorIgnoreBlank)
12459 {
12460 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12461 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12462 }
12463 else
12464 {
12465 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12466 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12467 }
12468
12469 large_dialog(recolor_4bit_dlg);
12470 large_dialog(recolor_8bit_dlg);
12471
12472 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12473 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12474 {
12475 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12476 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12477 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12478 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12479
12480 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12481 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12482 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12483 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12484 recolor_8bit_dlg[MR8_PALETTE].x++;
12485 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12486 recolor_8bit_dlg[MR8_PALETTE].y++;
12487 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12488 }
12489 }
12490
12491 static void massRecolorApplyChanges()
12492 {
12493 massRecolor8BitCSets=0;
12494 for(int32_t i=0; i<=13; i++)
12495 {
12496 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12497 massRecolor8BitCSets|=1<<i;
12498 }
12499
12500 if(massRecolorType==MR_4BIT)
12501 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12502 else
12503 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12504 }
12505
12506 static bool massRecolorSetup(int32_t cset)
12507 {
12508 massRecolorInit(cset);
12509
12510 // Remember the current colors in case the user cancels.
12511 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12512 for(int32_t i=0; i<16; i++)
12513 {
12514 oldDest4Bit[i]=massRecolorDest4Bit[i];
12515 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12516 oldDest8Bit[i]=massRecolorDest8Bit[i];
12517 }
12518
12519 byte type=massRecolorType;
12520 int32_t ret;
12521 do
12522 {
12523 HANDLE_CLOSE_ZQDLG();
12524 if(exiting_program) break;
12525 if(type==MR_4BIT)
12526 {
12527 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12528 if(ret==MR4_SWITCH)
12529 type=MR_8BIT;
12530 }
12531 else
12532 {
12533 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12534 if(ret==MR8_SWITCH)
12535 type=MR_4BIT;
12536 }
12537 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12538
12539 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12540 {
12541 for(int32_t i=0; i<16; i++)
12542 {
12543 massRecolorDest4Bit[i]=oldDest4Bit[i];
12544 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12545 massRecolorDest8Bit[i]=oldDest8Bit[i];
12546 }
12547 return false;
12548 }
12549
12550 // OK
12551 massRecolorType=type;
12552 massRecolorApplyChanges();
12553 return true;
12554 }
12555
12556 static void massRecolorApply4Bit(int32_t tile)
12557 {
12558 byte buf[256];
12559 unpack_tile(newtilebuf, tile, 0, true);
12560
12561 if(newtilebuf[tile].format==tf4Bit)
12562 {
12563 for(int32_t i=0; i<256; i++)
12564 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12565 }
12566 else // 8-bit
12567 {
12568 for(int32_t i=0; i<256; i++)
12569 {
12570 word cset=unpackbuf[i]>>4;
12571 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12572 {
12573 word color=unpackbuf[i]&15;
12574 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12575 }
12576 else
12577 buf[i]=unpackbuf[i];
12578 }
12579 }
12580
12581 pack_tile(newtilebuf, buf, tile);
12582 }
12583
12584 static void massRecolorApply8Bit(int32_t tile)
12585 {
12586 byte buf[256];
12587 unpack_tile(newtilebuf, tile, 0, true);
12588
12589 for(int32_t i=0; i<256; i++)
12590 {
12591 byte color=unpackbuf[i];
12592 for(int32_t j=0; j<16; j++)
12593 {
12594 if(massRecolorSrc8Bit[j]==color)
12595 {
12596 color=massRecolorDest8Bit[j];
12597 break;
12598 }
12599 }
12600 buf[i]=color;
12601 }
12602
12603 pack_tile(newtilebuf, buf, tile);
12604 }
12605
12606 static void massRecolorApply(int32_t tile)
12607 {
12608 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12609 return;
12610
12611 if(massRecolorType==MR_4BIT)
12612 massRecolorApply4Bit(tile);
12613 else // 8-bit
12614 {
12615 if(newtilebuf[tile].format==tf4Bit)
12616 return;
12617 massRecolorApply8Bit(tile);
12618 }
12619 }
12620
12621 static void massRecolorReset4Bit()
12622 {
12623 for(int32_t i=0; i<16; i++)
12624 massRecolorDest4Bit[i]=i;
12625 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12626 }
12627
12628 static void massRecolorReset8Bit()
12629 {
12630 for(int32_t i=0; i<16; i++)
12631 {
12632 massRecolorSrc8Bit[i]=0;
12633 massRecolorDest8Bit[i]=0;
12634 }
12635
12636 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12637 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12638 }
12639
12640 6 void center_zq_tiles_dialogs()
12641 {
12642 6 jwin_center_dialog(create_relational_tiles_dlg);
12643 6 jwin_center_dialog(icon_dlg);
12644 6 jwin_center_dialog(leech_dlg);
12645 6 jwin_center_dialog(move_textbox_list_dlg);
12646 6 jwin_center_dialog(recolor_4bit_dlg);
12647 6 jwin_center_dialog(recolor_8bit_dlg);
12648 6 }
12649
12650 //.ZCOMBO
12651
12652 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12653 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12654
12655 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12656 dword section_version, dword section_cversion, int32_t index, int32_t count)
12657 {
12658 newcombo temp_combo;
12659 for ( int32_t tilect = 0; tilect < count; tilect++ )
12660 {
12661 temp_combo.clear();
12662 if(!p_igetw(&temp_combo.tile,f))
12663 {
12664 return 0;
12665 }
12666 temp_combo.o_tile = temp_combo.tile;
12667
12668 if(!p_getc(&temp_combo.flip,f))
12669 {
12670 return 0;
12671 }
12672
12673 if(!p_getc(&temp_combo.walk,f))
12674 {
12675 return 0;
12676 }
12677
12678 if(!p_getc(&temp_combo.type,f))
12679 {
12680 return 0;
12681 }
12682
12683 if(!p_getc(&temp_combo.csets,f))
12684 {
12685 return 0;
12686 }
12687
12688 if(!p_getc(&temp_combo.frames,f))
12689 {
12690 return 0;
12691 }
12692
12693 if(!p_getc(&temp_combo.speed,f))
12694 {
12695 return 0;
12696 }
12697
12698 if(!p_igetw(&temp_combo.nextcombo,f))
12699 {
12700 return 0;
12701 }
12702
12703 if(!p_getc(&temp_combo.nextcset,f))
12704 {
12705 return 0;
12706 }
12707
12708 if(!p_getc(&temp_combo.flag,f))
12709 {
12710 return 0;
12711 }
12712
12713 if(!p_getc(&temp_combo.skipanim,f))
12714 {
12715 return 0;
12716 }
12717
12718 if(!p_igetw(&temp_combo.nexttimer,f))
12719 {
12720 return 0;
12721 }
12722
12723 if(!p_getc(&temp_combo.skipanimy,f))
12724 {
12725 return 0;
12726 }
12727
12728 if(!p_getc(&temp_combo.animflags,f))
12729 {
12730 return 0;
12731 }
12732
12733 //2.55 starts here
12734 if ( zversion >= 0x255 )
12735 {
12736 if ( section_version >= 12 )
12737 {
12738 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12739 {
12740 if(!p_igetl(&temp_combo.attributes[q],f))
12741 {
12742 return 0;
12743 }
12744 }
12745 if(!p_igetl(&temp_combo.usrflags,f))
12746 {
12747 return 0;
12748 }
12749 for ( int32_t q = 0; q < 3; q++ )
12750 {
12751 if(!p_igetl(&temp_combo.triggerflags[q],f))
12752 {
12753 return 0;
12754 }
12755 }
12756
12757 if(!p_igetl(&temp_combo.triggerlevel,f))
12758 {
12759 return 0;
12760 }
12761 if(section_version >= 22)
12762 {
12763 if(!p_getc(&temp_combo.triggerbtn,f))
12764 {
12765 return 0;
12766 }
12767 }
12768 if(section_version < 23)
12769 {
12770 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12771 {
12772 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12773 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12774 case cTRIGGERGENERIC: case cCSWITCH:
12775 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12776 }
12777 }
12778 if(section_version >= 24)
12779 {
12780 if(!p_getc(&temp_combo.triggeritem,f))
12781 {
12782 return 0;
12783 }
12784 if(!p_getc(&temp_combo.trigtimer,f))
12785 {
12786 return 0;
12787 }
12788 }
12789 if(section_version >= 25)
12790 {
12791 if(!p_getc(&temp_combo.trigsfx,f))
12792 {
12793 return 0;
12794 }
12795 }
12796 else
12797 {
12798 switch(temp_combo.type)
12799 {
12800 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12801 if(!(temp_combo.usrflags & cflag3))
12802 temp_combo.attribytes[3] = WAV_DOOR;
12803 temp_combo.usrflags &= ~cflag3;
12804 break;
12805 }
12806 }
12807 if(section_version < 26)
12808 {
12809 if(temp_combo.type == cARMOS)
12810 {
12811 if(temp_combo.usrflags & cflag1)
12812 temp_combo.usrflags |= cflag3;
12813 }
12814 }
12815 if(section_version >= 27)
12816 {
12817 if(!p_igetl(&temp_combo.trigchange,f))
12818 {
12819 return qe_invalid;
12820 }
12821 }
12822 else
12823 {
12824 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12825 temp_combo.trigchange = 1;
12826 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12827 temp_combo.trigchange = -1;
12828 else temp_combo.trigchange = 0;
12829 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12830 }
12831 if(section_version >= 29)
12832 {
12833 if(!p_igetw(&temp_combo.trigprox,f))
12834 {
12835 return qe_invalid;
12836 }
12837 if(!p_getc(&temp_combo.trigctr,f))
12838 {
12839 return qe_invalid;
12840 }
12841 if(!p_igetl(&temp_combo.trigctramnt,f))
12842 {
12843 return qe_invalid;
12844 }
12845 }
12846 else
12847 {
12848 temp_combo.trigprox = 0;
12849 temp_combo.trigctr = 0;
12850 temp_combo.trigctramnt = 0;
12851 }
12852 if(section_version >= 30)
12853 {
12854 if(!p_getc(&temp_combo.triglbeam,f))
12855 {
12856 return qe_invalid;
12857 }
12858 }
12859 else temp_combo.triglbeam = 0;
12860 if(section_version >= 31)
12861 {
12862 if(!p_getc(&temp_combo.trigcschange,f))
12863 {
12864 return qe_invalid;
12865 }
12866 if(!p_igetw(&temp_combo.spawnitem,f))
12867 {
12868 return qe_invalid;
12869 }
12870 if(!p_igetw(&temp_combo.spawnenemy,f))
12871 {
12872 return qe_invalid;
12873 }
12874 if(!p_getc(&temp_combo.exstate,f))
12875 {
12876 return qe_invalid;
12877 }
12878 if(!p_igetl(&temp_combo.spawnip,f))
12879 {
12880 return qe_invalid;
12881 }
12882 if(!p_getc(&temp_combo.trigcopycat,f))
12883 {
12884 return qe_invalid;
12885 }
12886 }
12887 else
12888 {
12889 temp_combo.trigcschange = 0;
12890 temp_combo.spawnitem = 0;
12891 temp_combo.spawnenemy = 0;
12892 temp_combo.exstate = -1;
12893 temp_combo.spawnip = 0;
12894 temp_combo.trigcopycat = 0;
12895 }
12896 if(section_version >= 32)
12897 {
12898 if(!p_getc(&temp_combo.trigcooldown,f))
12899 {
12900 return qe_invalid;
12901 }
12902 }
12903 else
12904 {
12905 temp_combo.trigcooldown = 0;
12906 }
12907 char label[12];
12908 label[11] = '\0';
12909 for ( int32_t q = 0; q < 11; q++ )
12910 {
12911 if(!p_getc(&label[q],f))
12912 {
12913 return 0;
12914 }
12915 }
12916 temp_combo.label = label;
12917 }
12918 if ( section_version >= 13 )
12919 {
12920 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12921 {
12922 if(!p_getc(&temp_combo.attribytes[q],f))
12923 {
12924 return 0;
12925 }
12926 }
12927
12928 }
12929 }
12930
12931 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12932 {
12933 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12934 {
12935 combobuf[index+(tilect)] = temp_combo;
12936 }
12937 }
12938 }
12939
12940 return 1;
12941 }
12942
12943 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12944 {
12945 dword section_version=0;
12946 dword section_cversion=0;
12947 int32_t zversion = 0;
12948 int32_t zbuild = 0;
12949
12950 if(!p_igetl(&zversion,f))
12951 {
12952 return 0;
12953 }
12954 if(!p_igetl(&zbuild,f))
12955 {
12956 return 0;
12957 }
12958 if(!p_igetw(&section_version,f))
12959 {
12960 return 0;
12961 }
12962 if(!p_igetw(&section_cversion,f))
12963 {
12964 return 0;
12965 }
12966
12967 if ( zversion > ZELDA_VERSION )
12968 {
12969 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12970 return 0;
12971 }
12972
12973 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12974 {
12975 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12976 return 0;
12977
12978 }
12979 else
12980 {
12981 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12982 }
12983
12984 int32_t index = 0;
12985 int32_t count = 0;
12986
12987 //tile id
12988 if(!p_igetl(&index,f))
12989 {
12990 return 0;
12991 }
12992 if(start > -1) index = start;
12993 // al_trace("Reading combo: index(%d)\n", index);
12994
12995 //tile count
12996 if(!p_igetl(&count,f))
12997 {
12998 return 0;
12999 }
13000 // al_trace("Reading combo: count(%d)\n", count);
13001 reset_combo_animations();
13002 reset_combo_animations2();
13003
13004 if(section_version < 33)
13005 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13006
13007 newcombo temp_combo;
13008 size_t end = index+count;
13009 for ( size_t q = index; q < end; q++ )
13010 {
13011 auto ret = readcombo_loop(f,section_version,temp_combo);
13012 if(ret) return 0;
13013
13014 if ( !(skip && q-1 < skip) )
13015 {
13016 if ( !nooverwrite || combobuf[q].is_blank() )
13017 {
13018 combobuf[q] = temp_combo;
13019 }
13020 }
13021 }
13022
13023 return 1;
13024 }
13025 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13026 {
13027 return readcombofile(f,skip,nooverwrite,start);
13028 }
13029 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13030 {
13031 dword section_version=V_COMBOS;
13032 dword section_cversion=CV_COMBOS;
13033 int32_t zversion = ZELDA_VERSION;
13034 int32_t zbuild = VERSION_BUILD;
13035
13036 if(!p_iputl(zversion,f))
13037 {
13038 return 0;
13039 }
13040 if(!p_iputl(zbuild,f))
13041 {
13042 return 0;
13043 }
13044 if(!p_iputw(section_version,f))
13045 {
13046 return 0;
13047 }
13048
13049 if(!p_iputw(section_cversion,f))
13050 {
13051 return 0;
13052 }
13053
13054 //start tile id
13055 if(!p_iputl(index,f))
13056 {
13057 return 0;
13058 }
13059
13060 //count
13061 if(!p_iputl(count,f))
13062 {
13063 return 0;
13064 }
13065 reset_combo_animations();
13066 reset_combo_animations2();
13067 size_t end = index+count;
13068 for(size_t q = index; q < end; ++q)
13069 {
13070 if(writecombo_loop(f, section_version, combobuf[q]))
13071 return 0;
13072 }
13073
13074 return 1;
13075
13076 }
13077
13078 //.ZALIAS
13079
13080
13081 //.ZALIAS
13082
13083 int32_t readcomboaliasfile(PACKFILE *f)
13084 {
13085 dword section_version=0;
13086 dword section_cversion=0;
13087 int32_t zversion = 0;
13088 int32_t zbuild = 0;
13089 word tempword = 0;
13090
13091 if(!p_igetl(&zversion,f))
13092 {
13093 return 0;
13094 }
13095 if(!p_igetl(&zbuild,f))
13096 {
13097 return 0;
13098 }
13099 if(!p_igetw(&section_version,f))
13100 {
13101 return 0;
13102 }
13103 if(!p_igetw(&section_cversion,f))
13104 {
13105 return 0;
13106 }
13107 al_trace("readoneweapon section_version: %d\n", section_version);
13108 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13109
13110 if ( zversion > ZELDA_VERSION )
13111 {
13112 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13113 return 0;
13114 }
13115
13116 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13117 {
13118 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13119 return 0;
13120
13121 }
13122 else
13123 {
13124 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13125 }
13126
13127 int32_t index = 0;
13128 int32_t count = 0;
13129 int32_t count2 = 0;
13130 byte tempcset = 0;
13131
13132 //tile id
13133 if(!p_igetl(&index,f))
13134 {
13135 return 0;
13136 }
13137 al_trace("Reading combo: index(%d)\n", index);
13138
13139 //tile count
13140 if(!p_igetl(&count,f))
13141 {
13142 return 0;
13143 }
13144 al_trace("Reading combo: count(%d)\n", count);
13145
13146 combo_alias temp_alias;
13147 memset(&temp_alias, 0, sizeof(temp_alias));
13148
13149 for ( int32_t tilect = 0; tilect < count; tilect++ )
13150 {
13151 memset(&temp_alias, 0, sizeof(temp_alias));
13152 if(!p_igetw(&temp_alias.combo,f))
13153 {
13154 return 0;
13155 }
13156
13157 if(!p_getc(&temp_alias.cset,f))
13158 {
13159 return 0;
13160 }
13161
13162
13163
13164 if(!p_igetl(&count2,f))
13165 {
13166 return 0;
13167 }
13168 al_trace("Read, Combo alias count is: %d\n", count2);
13169 if(!p_getc(&temp_alias.width,f))
13170 {
13171 return 0;
13172 }
13173
13174 if(!p_getc(&temp_alias.height,f))
13175 {
13176 return 0;
13177 }
13178
13179 if(!p_getc(&temp_alias.layermask,f))
13180 {
13181 return 0;
13182 }
13183 //These values are flexible, and may differ in size, so we delete them
13184 //and recreate them at the correct size on the pointer.
13185 temp_alias.combos.clear();
13186 temp_alias.csets.clear();
13187 for(int32_t k=0; k<count2; k++)
13188 {
13189 if(!p_igetw(&tempword,f))
13190 {
13191 return 0;
13192 }
13193 else
13194 {
13195
13196
13197 temp_alias.combos[k] = tempword;
13198 }
13199 }
13200
13201 for(int32_t k=0; k<count2; k++)
13202 {
13203 if(!p_getc(&tempcset,f))
13204 //if(!p_getc(&temp_alias.csets[k],f))
13205 {
13206 return 0;
13207 }
13208 else
13209 {
13210
13211 temp_alias.csets[k] = tempcset;
13212 }
13213 }
13214 memcpy(&combo_aliases[index+(tilect)],&temp_alias,sizeof(combo_alias));
13215 }
13216
13217 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13218
13219
13220 return 1;
13221
13222 }
13223
13224 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13225 {
13226 dword section_version=0;
13227 dword section_cversion=0;
13228 int32_t zversion = 0;
13229 int32_t zbuild = 0;
13230
13231 if(!p_igetl(&zversion,f))
13232 {
13233 return 0;
13234 }
13235 if(!p_igetl(&zbuild,f))
13236 {
13237 return 0;
13238 }
13239 if(!p_igetw(&section_version,f))
13240 {
13241 return 0;
13242 }
13243 if(!p_igetw(&section_cversion,f))
13244 {
13245 return 0;
13246 }
13247 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13248 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13249
13250 if ( zversion > ZELDA_VERSION )
13251 {
13252 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13253 return 0;
13254 }
13255 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13256 {
13257 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13258 return 0;
13259
13260 }
13261 else
13262 {
13263 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13264 }
13265
13266 int32_t index = 0;
13267 int32_t count = 0;
13268 int32_t count2 = 0;
13269 byte tempcset = 0;
13270 word tempword = 0;
13271
13272
13273 //tile id
13274 if(!p_igetl(&index,f))
13275 {
13276 return 0;
13277 }
13278 al_trace("Reading tile: index(%d)\n", index);
13279
13280 //tile count
13281 if(!p_igetl(&count,f))
13282 {
13283 return 0;
13284 }
13285 al_trace("Reading tile: count(%d)\n", count);
13286
13287
13288 combo_alias temp_alias;
13289 memset(&temp_alias, 0, sizeof(temp_alias));
13290
13291 for ( int32_t tilect = 0; tilect < count; tilect++ )
13292 {
13293 memset(&temp_alias, 0, sizeof(temp_alias));
13294 if(!p_igetw(&temp_alias.combo,f))
13295 {
13296 return 0;
13297 }
13298
13299 if(!p_getc(&temp_alias.cset,f))
13300 {
13301 return 0;
13302 }
13303
13304 int32_t count2 = 0;
13305
13306 if(!p_igetl(&count2,f))
13307 {
13308 return 0;
13309 }
13310
13311 if(!p_getc(&temp_alias.width,f))
13312 {
13313 return 0;
13314 }
13315
13316 if(!p_getc(&temp_alias.height,f))
13317 {
13318 return 0;
13319 }
13320
13321 if(!p_getc(&temp_alias.layermask,f))
13322 {
13323 return 0;
13324 }
13325 //These values are flexible, and may differ in size, so we delete them
13326 //and recreate them at the correct size on the pointer.
13327 temp_alias.combos.clear();
13328 temp_alias.csets.clear();
13329
13330 for(int32_t k=0; k<count2; k++)
13331 {
13332 if(!p_igetw(&tempword,f))
13333 {
13334 return 0;
13335 }
13336 else
13337 {
13338 temp_alias.combos[k] = tempword;
13339 }
13340 }
13341
13342 for(int32_t k=0; k<count2; k++)
13343 {
13344 if(!p_getc(&tempcset,f))
13345 {
13346 return 0;
13347 }
13348 else
13349 {
13350 temp_alias.csets[k] = tempcset;
13351 }
13352 }
13353
13354 if ( start+(tilect) < MAXCOMBOALIASES )
13355 {
13356 memcpy(&combo_aliases[start+(tilect)],&temp_alias,sizeof(temp_alias));
13357 }
13358 }
13359 return 1;
13360 }
13361 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13362 {
13363 al_trace("Running writecomboaliasfile\n");
13364 dword section_version=V_COMBOALIASES;
13365 dword section_cversion=CV_COMBOALIASES;
13366 int32_t zversion = ZELDA_VERSION;
13367 int32_t zbuild = VERSION_BUILD;
13368
13369 if(!p_iputl(zversion,f))
13370 {
13371 return 0;
13372 }
13373 if(!p_iputl(zbuild,f))
13374 {
13375 return 0;
13376 }
13377 if(!p_iputw(section_version,f))
13378 {
13379 return 0;
13380 }
13381
13382 if(!p_iputw(section_cversion,f))
13383 {
13384 return 0;
13385 }
13386
13387 //start tile id
13388 if(!p_iputl(index,f))
13389 {
13390 return 0;
13391 }
13392
13393 //count
13394 if(!p_iputl(count,f))
13395 {
13396 return 0;
13397 }
13398
13399 for ( int32_t tilect = 0; tilect < count; tilect++ )
13400 {
13401
13402 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13403 {
13404 return 0;
13405 }
13406
13407 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13408 {
13409 return 0;
13410 }
13411
13412 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13413
13414 if(!p_iputl(count2,f))
13415 {
13416 return 0;
13417 }
13418 al_trace("Write`, Combo alias count is: %d\n", count2);
13419
13420 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13421 {
13422 return 0;
13423 }
13424
13425 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13426 {
13427 return 0;
13428 }
13429
13430 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13431 {
13432 return 0;
13433 }
13434
13435 for(int32_t k=0; k<count2; k++)
13436 {
13437 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13438 {
13439 return 0;
13440 }
13441 }
13442
13443 for(int32_t k=0; k<count2; k++)
13444 {
13445 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13446 {
13447 return 0;
13448 }
13449 }
13450 }
13451
13452 return 1;
13453
13454 }
13455